rafia_stpa/stpa/
uca_contexts.rs1use std::{
17 ffi::OsStr,
18 fs::{self, File},
19 path::Path,
20};
21
22use csv;
23use serde::{Deserialize, Serialize};
24use serde_yaml;
25
26use crate::stpa::LoadError;
27
28#[derive(Debug, Serialize, Deserialize)]
29pub struct UcaContextCsv {
30 #[serde(rename = "Context Id")]
31 pub id: String,
32 #[serde(rename = "Unsafe Context")]
33 pub unsafe_context: String,
34 #[serde(rename = "Notes")]
35 pub notes: String,
36}
37
38#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
39pub struct UcaContext {
40 pub id: String,
41 pub unsafe_context: String,
42 pub notes: String,
43}
44
45impl UcaContext {
46 pub fn describe(&self) -> serde_json::Value {
47 serde_json::json!({"uca_context": self})
48 }
49}
50
51impl From<UcaContextCsv> for UcaContext {
52 fn from(csv: UcaContextCsv) -> Self {
53 UcaContext {
54 id: csv.id,
55 unsafe_context: csv.unsafe_context,
56 notes: csv.notes,
57 }
58 }
59}
60
61#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Default)]
62pub struct UcaContexts {
63 pub uca_contexts: Vec<UcaContext>,
64}
65
66impl UcaContexts {
67 pub fn from_yaml(text: &str) -> Result<UcaContexts, LoadError> {
68 serde_yaml::from_str::<UcaContexts>(text).map_err(LoadError::Yaml)
69 }
70 pub fn to_yaml(&self) -> Result<String, LoadError> {
71 serde_yaml::to_string(&self).map_err(LoadError::Yaml)
72 }
73 pub fn from_csv(filename: &Path) -> Result<UcaContexts, LoadError> {
74 let mut uca_contexts = vec![];
75 let file = File::open(filename)?;
76 for uca_context in csv::ReaderBuilder::new()
77 .from_reader(file)
78 .deserialize::<UcaContextCsv>()
79 {
80 uca_contexts.push(uca_context?.into());
81 }
82 Ok(UcaContexts { uca_contexts })
83 }
84 pub fn from_file(filename: &Path) -> Result<UcaContexts, LoadError> {
85 match filename.extension().and_then(OsStr::to_str) {
86 Some("csv") => Self::from_csv(filename),
87 Some("yml") | Some("yaml") => {
88 let text = fs::read_to_string(filename)?;
89 Self::from_yaml(&text)
90 }
91 _ => Err(LoadError::NotSupportedFormat),
92 }
93 }
94 pub fn find(&self, id: &str) -> Option<&UcaContext> {
95 self.uca_contexts.iter().find(|uca| uca.id == id)
96 }
97}