1use std::collections::BTreeMap;
13use std::fmt::Write;
14
15use super::fetch::FetchPlan;
16use super::manifest::{Extension, Lib};
17
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct Lockfile {
20 pub assay: Option<String>,
21 pub extensions: Vec<LockExtension>,
22 pub libs: Vec<LockLib>,
23}
24
25#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct LockExtension {
27 pub name: String,
28 pub version: String,
29 pub url: String,
30 pub sha256: BTreeMap<String, String>,
32}
33
34#[derive(Debug, Clone, PartialEq, Eq)]
35pub struct LockLib {
36 pub name: String,
37 pub version: String,
38 pub url: String,
39 pub sha256: String,
40}
41
42impl LockExtension {
43 pub fn new(ext: &Extension, plan: &FetchPlan) -> Self {
44 let sha256 = ext.sha256.iter().map(|(k, v)| (k.clone(), v.clone())).collect();
45 LockExtension {
46 name: ext.name.clone(),
47 version: ext.version.clone(),
48 url: plan.url.clone(),
49 sha256,
50 }
51 }
52}
53
54impl LockLib {
55 pub fn new(lib: &Lib, plan: &FetchPlan) -> Self {
56 LockLib {
57 name: lib.name.clone(),
58 version: lib.version.clone(),
59 url: plan.url.clone(),
60 sha256: lib.sha256.clone(),
61 }
62 }
63}
64
65impl Lockfile {
66 pub fn to_lua(&self) -> String {
68 let mut out = String::with_capacity(256);
69 out.push_str("-- Generated by `assay install`. Do not edit by hand.\n");
70 out.push_str("return {\n");
71
72 if let Some(v) = &self.assay {
73 writeln!(out, " assay = {},", lua_string(v)).unwrap();
74 }
75
76 out.push_str(" extensions = {\n");
77 for e in &self.extensions {
78 writeln!(out, " {{").unwrap();
79 writeln!(out, " name = {},", lua_string(&e.name)).unwrap();
80 writeln!(out, " version = {},", lua_string(&e.version)).unwrap();
81 writeln!(out, " url = {},", lua_string(&e.url)).unwrap();
82 out.push_str(" sha256 = {");
83 let mut first = true;
84 for (arch, hash) in &e.sha256 {
85 if !first {
86 out.push(',');
87 }
88 write!(out, " {arch} = {}", lua_string(hash)).unwrap();
89 first = false;
90 }
91 out.push_str(" },\n");
92 writeln!(out, " }},").unwrap();
93 }
94 out.push_str(" },\n");
95
96 out.push_str(" libs = {\n");
97 for l in &self.libs {
98 writeln!(out, " {{").unwrap();
99 writeln!(out, " name = {},", lua_string(&l.name)).unwrap();
100 writeln!(out, " version = {},", lua_string(&l.version)).unwrap();
101 writeln!(out, " url = {},", lua_string(&l.url)).unwrap();
102 writeln!(out, " sha256 = {},", lua_string(&l.sha256)).unwrap();
103 writeln!(out, " }},").unwrap();
104 }
105 out.push_str(" },\n");
106
107 out.push_str("}\n");
108 out
109 }
110}
111
112fn lua_string(s: &str) -> String {
113 let mut out = String::with_capacity(s.len() + 2);
114 out.push('"');
115 for c in s.chars() {
116 match c {
117 '\\' => out.push_str("\\\\"),
118 '"' => out.push_str("\\\""),
119 '\n' => out.push_str("\\n"),
120 '\r' => out.push_str("\\r"),
121 '\t' => out.push_str("\\t"),
122 c if (c as u32) < 0x20 => write!(out, "\\{}", c as u32).unwrap(),
123 c => out.push(c),
124 }
125 }
126 out.push('"');
127 out
128}