Skip to main content

DevelopmentNodeEnvironment_MicrosoftVSCodeDependency_22NodeVersion_Bundle_Clean_Debug_ElectronProfile_EsbuildCompiler_Mountain/RPC/CocoonService/GenericRequest/
FileSystem.rs

1#![allow(non_snake_case, unused_variables, dead_code, unused_imports)]
2
3//! Generic-request file-system handlers for `process_mountain_request`.
4//! Handles `fs.*` / `file:*` / `readFile` / `writeFile` / `stat` / `readdir`
5//! aliases used by Cocoon's `FileSystemService` and `MountainGRPCClient`.
6
7use std::time::UNIX_EPOCH;
8
9use serde_json::{Value, json};
10use tonic::Response;
11
12use crate::Vine::Generated::{GenericResponse, RpcError};
13
14/// Build a successful `GenericResponse` with JSON-serialised value.
15pub fn OkResponse(RequestId:u64, Value:&impl serde::Serialize) -> Response<GenericResponse> {
16	let Bytes = serde_json::to_vec(Value).unwrap_or_default();
17	Response::new(GenericResponse { request_identifier:RequestId, result:Bytes, error:None })
18}
19
20/// Build an error `GenericResponse`.
21pub fn ErrResponse(RequestId:u64, Code:i32, Message:String) -> Response<GenericResponse> {
22	Response::new(GenericResponse {
23		request_identifier:RequestId,
24		result:Vec::new(),
25		error:Some(RpcError { code:Code, message:Message, data:Vec::new() }),
26	})
27}
28
29pub async fn HandleReadFile(RequestId:u64, Params:Value) -> Response<GenericResponse> {
30	let Path = Params
31		.as_str()
32		.or_else(|| Params.get("path").and_then(|V| V.as_str()))
33		.unwrap_or("");
34	match tokio::fs::read(Path).await {
35		Ok(Content) => OkResponse(RequestId, &Content),
36		Err(Error) => ErrResponse(RequestId, -32000, format!("fs.readFile: {}", Error)),
37	}
38}
39
40pub async fn HandleReadFileUri(RequestId:u64, Params:Value) -> Response<GenericResponse> {
41	let Uri = Params
42		.get("uri")
43		.and_then(|V| V.as_str())
44		.or_else(|| Params.as_str())
45		.unwrap_or("")
46		.replace("file://", "");
47	match tokio::fs::read(&Uri).await {
48		Ok(Content) => OkResponse(RequestId, &Content),
49		Err(Error) => ErrResponse(RequestId, -32000, format!("readFile: {}", Error)),
50	}
51}
52
53pub async fn HandleWriteFile(RequestId:u64, Params:Value) -> Response<GenericResponse> {
54	let Path = Params.get("path").and_then(|V| V.as_str()).unwrap_or("");
55	let Content:Vec<u8> = Params
56		.get("content")
57		.and_then(|V| V.as_array())
58		.map(|A| A.iter().filter_map(|B| B.as_u64().map(|N| N as u8)).collect())
59		.unwrap_or_default();
60	match tokio::fs::write(Path, &Content).await {
61		Ok(()) => OkResponse(RequestId, &Value::Null),
62		Err(Error) => ErrResponse(RequestId, -32000, format!("fs.writeFile: {}", Error)),
63	}
64}
65
66pub async fn HandleWriteFileUri(RequestId:u64, Params:Value) -> Response<GenericResponse> {
67	let Uri = Params.get("uri").and_then(|V| V.as_str()).unwrap_or("").replace("file://", "");
68	let Content:Vec<u8> = Params
69		.get("content")
70		.and_then(|V| V.as_array())
71		.map(|A| A.iter().filter_map(|B| B.as_u64().map(|N| N as u8)).collect())
72		.unwrap_or_default();
73	match tokio::fs::write(&Uri, &Content).await {
74		Ok(()) => OkResponse(RequestId, &Value::Null),
75		Err(Error) => ErrResponse(RequestId, -32000, format!("writeFile: {}", Error)),
76	}
77}
78
79pub async fn HandleStat(RequestId:u64, Params:Value) -> Response<GenericResponse> {
80	let Path = Params
81		.as_str()
82		.or_else(|| Params.get("path").and_then(|V| V.as_str()))
83		.unwrap_or("");
84	match tokio::fs::metadata(Path).await {
85		Ok(Meta) => {
86			let Mtime = Meta
87				.modified()
88				.ok()
89				.and_then(|T| T.duration_since(UNIX_EPOCH).ok())
90				.map(|D| D.as_millis() as u64)
91				.unwrap_or(0);
92			OkResponse(
93				RequestId,
94				&json!({
95					"type": if Meta.is_dir() { 2 } else { 1 },
96					"is_file": Meta.is_file(),
97					"is_directory": Meta.is_dir(),
98					"size": Meta.len(),
99					"mtime": Mtime,
100				}),
101			)
102		},
103		Err(Error) => ErrResponse(RequestId, -32000, format!("fs.stat: {}", Error)),
104	}
105}
106
107pub async fn HandleStatUri(RequestId:u64, Params:Value) -> Response<GenericResponse> {
108	let Uri = Params
109		.get("uri")
110		.and_then(|V| V.as_str())
111		.or_else(|| Params.as_str())
112		.unwrap_or("")
113		.replace("file://", "");
114	match tokio::fs::metadata(&Uri).await {
115		Ok(Meta) => {
116			let Mtime = Meta
117				.modified()
118				.ok()
119				.and_then(|T| T.duration_since(UNIX_EPOCH).ok())
120				.map(|D| D.as_millis() as u64)
121				.unwrap_or(0);
122			OkResponse(
123				RequestId,
124				&json!({
125					"type": if Meta.is_dir() { 2 } else { 1 },
126					"is_file": Meta.is_file(),
127					"is_directory": Meta.is_dir(),
128					"size": Meta.len(),
129					"mtime": Mtime,
130				}),
131			)
132		},
133		Err(Error) => ErrResponse(RequestId, -32000, format!("stat: {}", Error)),
134	}
135}
136
137pub async fn HandleReaddir(RequestId:u64, Params:Value) -> Response<GenericResponse> {
138	let Path = Params
139		.as_str()
140		.or_else(|| Params.get("path").and_then(|V| V.as_str()))
141		.unwrap_or("");
142	match tokio::fs::read_dir(Path).await {
143		Ok(mut Entries) => {
144			let mut Items:Vec<Value> = Vec::new();
145			while let Ok(Some(Entry)) = Entries.next_entry().await {
146				if let Some(Name) = Entry.file_name().to_str() {
147					let IsDir = Entry.file_type().await.map(|T| T.is_dir()).unwrap_or(false);
148					Items.push(json!({ "name": Name, "type": if IsDir { 2u32 } else { 1u32 } }));
149				}
150			}
151			OkResponse(RequestId, &Items)
152		},
153		Err(Error) => ErrResponse(RequestId, -32000, format!("fs.listDir: {}", Error)),
154	}
155}
156
157pub async fn HandleReaddirUri(RequestId:u64, Params:Value) -> Response<GenericResponse> {
158	let Uri = Params
159		.get("uri")
160		.and_then(|V| V.as_str())
161		.or_else(|| Params.as_str())
162		.unwrap_or("")
163		.replace("file://", "");
164	match tokio::fs::read_dir(&Uri).await {
165		Ok(mut Entries) => {
166			let mut Names:Vec<String> = Vec::new();
167			while let Ok(Some(Entry)) = Entries.next_entry().await {
168				if let Some(Name) = Entry.file_name().to_str() {
169					Names.push(Name.to_string());
170				}
171			}
172			OkResponse(RequestId, &Names)
173		},
174		Err(Error) => ErrResponse(RequestId, -32000, format!("readdir: {}", Error)),
175	}
176}
177
178pub async fn HandleCreateDir(RequestId:u64, Params:Value) -> Response<GenericResponse> {
179	let Path = Params
180		.as_str()
181		.or_else(|| Params.get("path").and_then(|V| V.as_str()))
182		.unwrap_or("");
183	match tokio::fs::create_dir_all(Path).await {
184		Ok(()) => OkResponse(RequestId, &Value::Null),
185		Err(Error) => ErrResponse(RequestId, -32000, format!("fs.createDir: {}", Error)),
186	}
187}
188
189pub async fn HandleDelete(RequestId:u64, Params:Value) -> Response<GenericResponse> {
190	let Path = Params
191		.as_str()
192		.or_else(|| Params.get("path").and_then(|V| V.as_str()))
193		.unwrap_or("");
194	let Result = if std::path::Path::new(Path).is_dir() {
195		tokio::fs::remove_dir_all(Path).await
196	} else {
197		tokio::fs::remove_file(Path).await
198	};
199	match Result {
200		Ok(()) => OkResponse(RequestId, &Value::Null),
201		Err(Error) => ErrResponse(RequestId, -32000, format!("fs.delete: {}", Error)),
202	}
203}
204
205pub async fn HandleRename(RequestId:u64, Params:Value) -> Response<GenericResponse> {
206	let From = Params.get("from").and_then(|V| V.as_str()).unwrap_or("");
207	let To = Params.get("to").and_then(|V| V.as_str()).unwrap_or("");
208	match tokio::fs::rename(From, To).await {
209		Ok(()) => OkResponse(RequestId, &Value::Null),
210		Err(Error) => ErrResponse(RequestId, -32000, format!("fs.rename: {}", Error)),
211	}
212}