1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00
ZoKrates/zokrates_fs_resolver/src/lib.rs

177 lines
5.5 KiB
Rust

use std::fs::File;
use std::io;
use std::io::BufReader;
use std::path::PathBuf;
const ZOKRATES_HOME: &str = &"ZOKRATES_HOME";
pub fn resolve(
location: &Option<String>,
source: &String,
) -> Result<(BufReader<File>, String, String), io::Error> {
// the fs resolver has to be provided a location, as it supports relative paths
match location {
Some(location) => resolve_with_location(location, source),
None => Err(io::Error::new(io::ErrorKind::Other, "No location provided")),
}
}
fn resolve_with_location(
location: &String,
source: &String,
) -> Result<(BufReader<File>, String, String), io::Error> {
let path = PathBuf::from(location).join(PathBuf::from(source));
let (next_location, alias) = generate_next_parameters(&path)?;
match File::open(path) {
Ok(f) => Ok((BufReader::new(f), next_location, alias)),
Err(e) => match e.kind() {
io::ErrorKind::NotFound => match std::env::var(ZOKRATES_HOME) {
Ok(v) => {
let path = PathBuf::from(v).join(PathBuf::from(source));
let (next_location, alias) = generate_next_parameters(&path)?;
File::open(path).and_then(|f| Ok((BufReader::new(f), next_location, alias)))
}
Err(_) => Err(e),
},
_ => Err(e),
},
}
}
fn generate_next_parameters(path: &PathBuf) -> Result<(String, String), io::Error> {
match (path.parent(), path.file_stem()) {
(Some(parent), Some(stem)) => Ok((
parent.to_path_buf().into_os_string().into_string().unwrap(),
stem.to_os_string().to_string_lossy().to_string(),
)),
_ => Err(io::Error::new(io::ErrorKind::Other, "Invalid path")),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn valid_path_with_location() {
let (_, next_location, alias) =
resolve(&Some(String::from("./src")), &String::from("lib.rs")).unwrap();
assert_eq!(next_location, String::from("./src"));
assert_eq!(alias, String::from("lib"));
}
#[test]
fn valid_path_without_location() {
let res = resolve(&None, &String::from("./src/lib.rs"));
assert!(res.is_err());
}
#[test]
fn non_existing_file() {
let res = resolve(&Some(String::from("./src")), &String::from("rubbish.rs"));
assert!(res.is_err());
}
#[test]
fn invalid_location() {
let res = resolve(&Some(String::from(",8!-$2abc")), &String::from("foo.code"));
assert!(res.is_err());
}
#[test]
fn invalid_file() {
let res = resolve(&Some(String::from("./src")), &String::from(",8!-$2abc"));
assert!(res.is_err());
}
#[test]
fn not_a_file() {
let res = resolve(&Some(String::from(".")), &String::from("/src/"));
assert!(res.is_err());
}
#[test]
fn no_parent() {
let res = resolve(&Some(String::from(".")), &String::from("."));
assert!(res.is_err());
}
#[test]
fn no_file_name() {
let res = resolve(&Some(String::from(".")), &String::from(""));
assert!(res.is_err());
}
#[test]
fn default_to_local() {
use std::io::BufRead;
use std::io::Write;
// create a HOME folder with a code file
let zokrates_home_folder = tempfile::tempdir().unwrap();
let file_path = zokrates_home_folder.path().join("bar.code");
let mut file = File::create(file_path).unwrap();
writeln!(file, "<stdlib code>").unwrap();
// create a user folder with a code file
let source_folder = tempfile::tempdir().unwrap();
let file_path = source_folder.path().join("bar.code");
let mut file = File::create(file_path).unwrap();
writeln!(file, "<user code>").unwrap();
// assign HOME folder to ZOKRATES_HOME
std::env::set_var(ZOKRATES_HOME, zokrates_home_folder.path());
let result = resolve(
&Some(
source_folder
.path()
.to_path_buf()
.to_string_lossy()
.to_string(),
),
&"bar.code".to_string(),
);
assert!(result.is_ok());
let mut code = String::new();
result.unwrap().0.read_line(&mut code).unwrap();
// the imported file should be the user's
assert_eq!(code, "<user code>\n".to_string());
}
#[test]
fn fallback_to_std() {
use std::io::BufRead;
use std::io::Write;
// create a HOME folder
let zokrates_home_folder = tempfile::tempdir().unwrap();
let file_path = zokrates_home_folder.path().join("bar.code");
let mut file = File::create(file_path).unwrap();
writeln!(file, "<stdlib code>").unwrap();
// assign HOME folder to ZOKRATES_HOME
std::env::set_var(ZOKRATES_HOME, zokrates_home_folder.path());
let result = resolve(
&Some("/path/to/user/folder".to_string()),
&"bar.code".to_string(),
);
assert!(result.is_ok());
let mut code = String::new();
result.unwrap().0.read_line(&mut code).unwrap();
// the imported file should be the one in $ZOKRATES_HOME
assert_eq!(code, "<stdlib code>\n".to_string());
}
#[test]
fn fail_if_no_std() {
std::env::set_var(ZOKRATES_HOME, "");
let result = resolve(
&Some("/path/to/source".to_string()),
&"bar.code".to_string(),
);
assert!(result.is_err());
}
}