1use std::borrow::Cow;
4
5use serde::{Deserialize, Serialize};
6
7use crate::conventions::Convention;
8use crate::graph::{CodeGraph, ContractView};
9use crate::ledger::Entry;
10use crate::manifests::InternalDep;
11use crate::model::{Edge, Symbol};
12
13pub struct Data {
15 pub graph: CodeGraph,
16 pub symbols: Vec<Symbol>,
17 pub edges: Vec<Edge>,
18 pub contracts: Vec<ContractView>,
19 pub entries: Vec<Entry>,
20 pub conventions: Vec<Convention>,
22 pub manual: Vec<crate::conventions::Manual>,
23 pub deps: Vec<InternalDep>,
24 pub root: Option<String>,
26 pub problem: Option<String>,
28}
29
30impl Data {
31 pub fn load(root: &str, verifier: &crate::signing::Verifier) -> anyhow::Result<Data> {
33 let dir = format!("{}/_graph", root.trim_end_matches('/'));
34 let (symbols, edges) = crate::index::read_graph_blocking(&dir)
35 .map_err(|e| anyhow::anyhow!("no index at {dir}: {e:#}"))?;
36 let mut conventions = match crate::index::read_facts_blocking(&dir) {
37 Ok(Some(facts)) => crate::conventions::mine(&symbols, &edges, &facts),
38 _ => Vec::new(),
39 };
40 conventions.extend(crate::index::read_recipes_blocking(&dir).unwrap_or_default());
41 let manual = crate::conventions::manual_blocking(root).unwrap_or_default();
42 let records = crate::ledger::all_blocking(root).unwrap_or_default();
43 let mut entries = crate::ledger::derive(&records, &symbols, verifier);
44 let packages = crate::index::read_packages_blocking(&dir).unwrap_or_default();
45 let findings = crate::checks::run(&entries, &symbols, &edges, &packages);
46 crate::checks::promote(&mut entries, &findings);
47 let deps = crate::manifests::internal(&packages);
48 let mut data = Data::from_view(View {
49 symbols: symbols.into(),
50 edges: edges.into(),
51 entries: entries.into(),
52 conventions: conventions.into(),
53 manual: manual.into(),
54 deps: deps.into(),
55 problem: None,
56 });
57 data.root = Some(root.to_string());
58 Ok(data)
59 }
60
61 pub fn from_view(v: View<'_>) -> Data {
63 let (symbols, edges) = (v.symbols.into_owned(), v.edges.into_owned());
64 let graph = CodeGraph::build(&symbols, &edges);
65 Data {
66 contracts: graph.contracts(None, false),
67 graph,
68 symbols,
69 edges,
70 entries: v.entries.into_owned(),
71 conventions: v.conventions.into_owned(),
72 manual: v.manual.into_owned(),
73 deps: v.deps.into_owned(),
74 root: None,
75 problem: v.problem,
76 }
77 }
78
79 pub fn empty(root: &str, problem: String) -> Data {
81 Data {
82 graph: CodeGraph::build(&[], &[]),
83 symbols: Vec::new(),
84 edges: Vec::new(),
85 contracts: Vec::new(),
86 entries: Vec::new(),
87 conventions: Vec::new(),
88 manual: Vec::new(),
89 deps: Vec::new(),
90 root: Some(root.to_string()),
91 problem: Some(problem),
92 }
93 }
94
95 pub fn load_or_empty(root: &str, verifier: &crate::signing::Verifier) -> Data {
97 Data::load(root, verifier).unwrap_or_else(|e| Data::empty(root, format!("{e:#}")))
98 }
99}
100
101#[derive(Serialize, Deserialize)]
103pub struct View<'a> {
104 pub symbols: Cow<'a, [Symbol]>,
105 pub edges: Cow<'a, [Edge]>,
106 pub entries: Cow<'a, [Entry]>,
108 pub conventions: Cow<'a, [Convention]>,
109 pub manual: Cow<'a, [crate::conventions::Manual]>,
110 pub deps: Cow<'a, [InternalDep]>,
111 pub problem: Option<String>,
112}