sim_run_loaders/
source.rs1use std::path::{Path, PathBuf};
8
9#[cfg(unix)]
10use std::{
11 ffi::OsString,
12 os::unix::ffi::{OsStrExt, OsStringExt},
13};
14
15use sim_kernel::{CatalogSource, Datum, Error, LibSource, LibSourceSpec, Result, Symbol};
16
17pub const PATH_SOURCE_KIND: &str = "path";
19pub const URL_SOURCE_KIND: &str = "url";
21pub const BYTES_SOURCE_KIND: &str = "bytes";
23pub const CONTENT_ADDRESS_SOURCE_KIND: &str = "content-address";
25
26pub fn path_source_kind() -> Symbol {
28 Symbol::new(PATH_SOURCE_KIND)
29}
30
31pub fn url_source_kind() -> Symbol {
33 Symbol::new(URL_SOURCE_KIND)
34}
35
36pub fn bytes_source_kind() -> Symbol {
38 Symbol::new(BYTES_SOURCE_KIND)
39}
40
41pub fn content_address_source_kind() -> Symbol {
43 Symbol::new(CONTENT_ADDRESS_SOURCE_KIND)
44}
45
46pub fn path_source(path: impl Into<PathBuf>) -> LibSource {
48 LibSource::open(path_source_kind(), path_payload(path.into()))
49}
50
51pub fn path_source_spec(path: impl Into<PathBuf>) -> LibSourceSpec {
53 LibSourceSpec::open(path_source_kind(), path_payload(path.into()))
54}
55
56pub fn catalog_path_source(path: impl Into<PathBuf>) -> CatalogSource {
58 CatalogSource::open(path_source_kind(), path_payload(path.into()))
59}
60
61pub fn url_source(url: impl Into<String>) -> LibSource {
63 LibSource::open(url_source_kind(), Datum::String(url.into()))
64}
65
66pub fn url_source_spec(url: impl Into<String>) -> LibSourceSpec {
68 LibSourceSpec::open(url_source_kind(), Datum::String(url.into()))
69}
70
71pub fn catalog_url_source(url: impl Into<String>) -> CatalogSource {
73 CatalogSource::open(url_source_kind(), Datum::String(url.into()))
74}
75
76pub fn bytes_source(bytes: impl Into<Vec<u8>>) -> LibSource {
78 LibSource::open(bytes_source_kind(), Datum::Bytes(bytes.into()))
79}
80
81pub fn bytes_source_spec(bytes: impl Into<Vec<u8>>) -> LibSourceSpec {
83 LibSourceSpec::open(bytes_source_kind(), Datum::Bytes(bytes.into()))
84}
85
86pub fn catalog_bytes_source(bytes: impl Into<Vec<u8>>) -> CatalogSource {
88 CatalogSource::open(bytes_source_kind(), Datum::Bytes(bytes.into()))
89}
90
91pub fn content_address_source(payload: Datum) -> LibSource {
93 LibSource::open(content_address_source_kind(), payload)
94}
95
96pub fn content_address_source_spec(payload: Datum) -> LibSourceSpec {
98 LibSourceSpec::open(content_address_source_kind(), payload)
99}
100
101pub fn catalog_content_address_source(payload: Datum) -> CatalogSource {
103 CatalogSource::open(content_address_source_kind(), payload)
104}
105
106pub fn is_path_source(source: &LibSource) -> bool {
108 open_payload(source, &path_source_kind()).is_some()
109}
110
111pub fn is_url_source(source: &LibSource) -> bool {
113 open_payload(source, &url_source_kind()).is_some()
114}
115
116pub fn is_bytes_source(source: &LibSource) -> bool {
118 open_payload(source, &bytes_source_kind()).is_some()
119}
120
121pub fn path_from_source(source: &LibSource) -> Result<Option<PathBuf>> {
123 open_payload(source, &path_source_kind())
124 .map(path_from_payload)
125 .transpose()
126}
127
128pub fn url_from_source(source: &LibSource) -> Result<Option<String>> {
130 open_payload(source, &url_source_kind())
131 .map(url_from_payload)
132 .transpose()
133}
134
135pub fn bytes_from_source(source: &LibSource) -> Result<Option<Vec<u8>>> {
137 open_payload(source, &bytes_source_kind())
138 .map(bytes_from_payload)
139 .transpose()
140}
141
142pub fn content_address_payload(source: &LibSource) -> Option<&Datum> {
144 open_payload(source, &content_address_source_kind())
145}
146
147pub fn path_payload(path: impl AsRef<Path>) -> Datum {
149 #[cfg(unix)]
150 {
151 Datum::Bytes(path.as_ref().as_os_str().as_bytes().to_vec())
152 }
153
154 #[cfg(not(unix))]
155 {
156 Datum::String(path.as_ref().to_string_lossy().into_owned())
157 }
158}
159
160pub fn path_from_payload(payload: &Datum) -> Result<PathBuf> {
162 match payload {
163 Datum::String(path) => Ok(PathBuf::from(path)),
164 #[cfg(unix)]
165 Datum::Bytes(bytes) => Ok(PathBuf::from(OsString::from_vec(bytes.clone()))),
166 #[cfg(not(unix))]
167 Datum::Bytes(_) => Err(Error::HostError(
168 "path source byte payloads are only supported on unix".to_owned(),
169 )),
170 other => Err(Error::TypeMismatch {
171 expected: "path source string or bytes",
172 found: datum_kind(other),
173 }),
174 }
175}
176
177pub fn url_from_payload(payload: &Datum) -> Result<String> {
179 string_payload(payload)
180}
181
182pub fn bytes_from_payload(payload: &Datum) -> Result<Vec<u8>> {
184 bytes_payload(payload)
185}
186
187fn open_payload<'a>(source: &'a LibSource, expected_kind: &Symbol) -> Option<&'a Datum> {
188 match source {
189 LibSource::Open { kind, payload } if kind == expected_kind => Some(payload),
190 _ => None,
191 }
192}
193
194fn string_payload(payload: &Datum) -> Result<String> {
195 match payload {
196 Datum::String(value) => Ok(value.clone()),
197 other => Err(Error::TypeMismatch {
198 expected: "source string",
199 found: datum_kind(other),
200 }),
201 }
202}
203
204fn bytes_payload(payload: &Datum) -> Result<Vec<u8>> {
205 match payload {
206 Datum::Bytes(value) => Ok(value.clone()),
207 other => Err(Error::TypeMismatch {
208 expected: "source bytes",
209 found: datum_kind(other),
210 }),
211 }
212}
213
214fn datum_kind(datum: &Datum) -> &'static str {
215 match datum {
216 Datum::Nil => "datum nil",
217 Datum::Bool(_) => "datum bool",
218 Datum::Number(_) => "datum number",
219 Datum::Symbol(_) => "datum symbol",
220 Datum::String(_) => "datum string",
221 Datum::Bytes(_) => "datum bytes",
222 Datum::List(_) => "datum list",
223 Datum::Vector(_) => "datum vector",
224 Datum::Map(_) => "datum map",
225 Datum::Set(_) => "datum set",
226 Datum::Node { .. } => "datum node",
227 }
228}