1use std::collections::HashMap;
15
16use crate::value::{RuntimeError, Value, list_from_vec};
17
18pub fn register(global: &mut HashMap<String, Value>) {
19 let mut members = HashMap::new();
20 for method in &[
21 "readText",
22 "writeText",
23 "appendText",
24 "exists",
25 "delete",
26 "deleteDir",
27 "listDir",
28 "makeDir",
29 ] {
30 members.insert(
31 method.to_string(),
32 Value::Builtin(format!("Disk.{}", method)),
33 );
34 }
35 global.insert(
36 "Disk".to_string(),
37 Value::Namespace {
38 name: "Disk".to_string(),
39 members,
40 },
41 );
42}
43
44pub fn effects(name: &str) -> &'static [&'static str] {
45 match name {
46 "Disk.readText" => &["Disk.readText"],
47 "Disk.writeText" => &["Disk.writeText"],
48 "Disk.appendText" => &["Disk.appendText"],
49 "Disk.exists" => &["Disk.exists"],
50 "Disk.delete" => &["Disk.delete"],
51 "Disk.deleteDir" => &["Disk.deleteDir"],
52 "Disk.listDir" => &["Disk.listDir"],
53 "Disk.makeDir" => &["Disk.makeDir"],
54 _ => &[],
55 }
56}
57
58pub fn call(name: &str, args: &[Value]) -> Option<Result<Value, RuntimeError>> {
60 match name {
61 "Disk.readText" => Some(read_text(args)),
62 "Disk.writeText" => Some(write_text(args)),
63 "Disk.appendText" => Some(append_text(args)),
64 "Disk.exists" => Some(exists(args)),
65 "Disk.delete" => Some(delete(args)),
66 "Disk.deleteDir" => Some(delete_dir(args)),
67 "Disk.listDir" => Some(list_dir(args)),
68 "Disk.makeDir" => Some(make_dir(args)),
69 _ => None,
70 }
71}
72
73fn read_text(args: &[Value]) -> Result<Value, RuntimeError> {
76 let path = one_str_arg("Disk.readText", args)?;
77 match aver_rt::read_text(&path) {
78 Ok(text) => Ok(Value::Ok(Box::new(Value::Str(text)))),
79 Err(e) => Ok(Value::Err(Box::new(Value::Str(e.to_string())))),
80 }
81}
82
83fn write_text(args: &[Value]) -> Result<Value, RuntimeError> {
84 let (path, content) = two_str_args("Disk.writeText", args)?;
85 match aver_rt::write_text(&path, &content) {
86 Ok(_) => Ok(Value::Ok(Box::new(Value::Unit))),
87 Err(e) => Ok(Value::Err(Box::new(Value::Str(e.to_string())))),
88 }
89}
90
91fn append_text(args: &[Value]) -> Result<Value, RuntimeError> {
92 let (path, content) = two_str_args("Disk.appendText", args)?;
93 match aver_rt::append_text(&path, &content) {
94 Ok(_) => Ok(Value::Ok(Box::new(Value::Unit))),
95 Err(e) => Ok(Value::Err(Box::new(Value::Str(e.to_string())))),
96 }
97}
98
99fn exists(args: &[Value]) -> Result<Value, RuntimeError> {
100 let path = one_str_arg("Disk.exists", args)?;
101 Ok(Value::Bool(aver_rt::path_exists(&path)))
102}
103
104fn delete(args: &[Value]) -> Result<Value, RuntimeError> {
105 let path = one_str_arg("Disk.delete", args)?;
106 match aver_rt::delete_file(&path) {
107 Ok(_) => Ok(Value::Ok(Box::new(Value::Unit))),
108 Err(e) => Ok(Value::Err(Box::new(Value::Str(e.to_string())))),
109 }
110}
111
112fn delete_dir(args: &[Value]) -> Result<Value, RuntimeError> {
113 let path = one_str_arg("Disk.deleteDir", args)?;
114 match aver_rt::delete_dir(&path) {
115 Ok(_) => Ok(Value::Ok(Box::new(Value::Unit))),
116 Err(e) => Ok(Value::Err(Box::new(Value::Str(e.to_string())))),
117 }
118}
119
120fn list_dir(args: &[Value]) -> Result<Value, RuntimeError> {
121 let path = one_str_arg("Disk.listDir", args)?;
122 match aver_rt::list_dir(&path) {
123 Ok(entries) => Ok(Value::Ok(Box::new(list_from_vec(
124 entries.into_iter().map(Value::Str).collect(),
125 )))),
126 Err(e) => Ok(Value::Err(Box::new(Value::Str(e.to_string())))),
127 }
128}
129
130fn make_dir(args: &[Value]) -> Result<Value, RuntimeError> {
131 let path = one_str_arg("Disk.makeDir", args)?;
132 match aver_rt::make_dir(&path) {
133 Ok(_) => Ok(Value::Ok(Box::new(Value::Unit))),
134 Err(e) => Ok(Value::Err(Box::new(Value::Str(e.to_string())))),
135 }
136}
137
138fn one_str_arg(fn_name: &str, args: &[Value]) -> Result<String, RuntimeError> {
141 match args {
142 [Value::Str(s)] => Ok(s.clone()),
143 [_] => Err(RuntimeError::Error(format!(
144 "{}: path must be a String",
145 fn_name
146 ))),
147 _ => Err(RuntimeError::Error(format!(
148 "{}() takes 1 argument (path), got {}",
149 fn_name,
150 args.len()
151 ))),
152 }
153}
154
155fn two_str_args(fn_name: &str, args: &[Value]) -> Result<(String, String), RuntimeError> {
156 match args {
157 [Value::Str(a), Value::Str(b)] => Ok((a.clone(), b.clone())),
158 [_, _] => Err(RuntimeError::Error(format!(
159 "{}: both arguments must be Strings",
160 fn_name
161 ))),
162 _ => Err(RuntimeError::Error(format!(
163 "{}() takes 2 arguments (path, content), got {}",
164 fn_name,
165 args.len()
166 ))),
167 }
168}