1mod execution;
4mod model;
5mod protocol;
6mod publication;
7mod repository;
8mod sandbox;
9
10use std::fmt;
11use std::path::{Path, PathBuf};
12use std::time::Duration;
13
14pub use model::{Error, File, Result, RunRequest, RunResult, RustBinInput, RustBinOutput};
15use model::{ValidSource, validate_name, validate_source};
16pub use protocol::{read_input, write_output};
17
18pub const DEFAULT_RUN_TIMEOUT: Duration = Duration::from_secs(2 * 60);
20
21pub struct Lib {
23 pub files: Vec<File>,
25 repository: PathBuf,
26 name: String,
27 identity: String,
28 publications: PathBuf,
29}
30
31pub fn create(
33 rust_bins_root: impl AsRef<Path>,
34 publications_root: impl AsRef<Path>,
35 name: &str,
36) -> Result<Lib> {
37 validate_name(name)?;
38 let source = initial_source(name)?;
39 let snapshot = repository::create(rust_bins_root.as_ref(), name, &source)?;
40 Ok(Lib {
41 files: snapshot.files,
42 repository: snapshot.repository,
43 name: name.to_owned(),
44 identity: snapshot.identity,
45 publications: publications_root.as_ref().to_path_buf(),
46 })
47}
48
49pub fn open(
51 rust_bins_root: impl AsRef<Path>,
52 publications_root: impl AsRef<Path>,
53 name: &str,
54) -> Result<Lib> {
55 validate_name(name)?;
56 let snapshot = repository::open(rust_bins_root.as_ref(), name)?;
57 Ok(Lib {
58 files: snapshot.files,
59 repository: snapshot.repository,
60 name: name.to_owned(),
61 identity: snapshot.identity,
62 publications: publications_root.as_ref().to_path_buf(),
63 })
64}
65
66pub fn docs(rust_bins_root: impl AsRef<Path>, name: &str) -> Result<(String, String)> {
68 validate_name(name)?;
69 repository::docs(rust_bins_root.as_ref(), name)
70}
71
72pub fn run(
78 publications_root: impl AsRef<Path>,
79 name: &str,
80 version_selector: &str,
81 request: RunRequest,
82 timeout: Option<Duration>,
83) -> Result<RunResult> {
84 validate_name(name)?;
85 let publication = publication::resolve(publications_root.as_ref(), name, version_selector)?;
86 execution::run(
87 &publication.executable,
88 publication.version.to_string(),
89 request,
90 timeout.unwrap_or(DEFAULT_RUN_TIMEOUT),
91 )
92}
93
94impl Lib {
95 pub fn write(&mut self) -> Result<()> {
97 let source = validate_source(&self.files, &self.name)?;
98 let snapshot = repository::replace(&self.repository, &self.identity, &source)?;
99 self.files = snapshot.files;
100 self.identity = snapshot.identity;
101 Ok(())
102 }
103
104 pub fn check(&self) -> Result<()> {
106 let source = validate_source(&self.files, &self.name)?;
107 sandbox::check(&source, &self.name)
108 }
109
110 pub fn publish(&self) -> Result<()> {
112 let source = validate_source(&self.files, &self.name)?;
113 let executable = sandbox::build(&source, &self.name)?;
114 publication::publish(&self.publications, &self.name, &source.version, &executable)
115 }
116}
117
118impl fmt::Debug for Lib {
119 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
120 formatter
121 .debug_struct("Lib")
122 .field("files", &self.files)
123 .field("repository", &self.repository)
124 .field("name", &self.name)
125 .field("identity", &"[PRIVATE]")
126 .field("publications", &self.publications)
127 .finish()
128 }
129}
130
131fn initial_source(name: &str) -> Result<ValidSource> {
132 validate_source(
133 &[
134 File {
135 path: "Cargo.toml".to_owned(),
136 contents: format!(
137 "[package]\nname = \"{name}\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
138 ),
139 },
140 File {
141 path: "Documentation.md".to_owned(),
142 contents: String::new(),
143 },
144 File {
145 path: "src/main.rs".to_owned(),
146 contents: "fn main() {}\n".to_owned(),
147 },
148 ],
149 name,
150 )
151}