use super::{
parse_response, vfs_request, FileMetadata, SeekFrom, VfsAction, VfsError, VfsResponse,
};
use crate::{get_blob, PackageId};
pub struct File {
pub path: String,
pub timeout: u64,
}
impl File {
pub fn new<T: Into<String>>(path: T, timeout: u64) -> Self {
Self {
path: path.into(),
timeout,
}
}
pub fn read(&self) -> Result<Vec<u8>, VfsError> {
let message = vfs_request(&self.path, VfsAction::Read)
.send_and_await_response(self.timeout)
.unwrap()
.map_err(|e| VfsError::SendError(e.kind))?;
match parse_response(message.body())? {
VfsResponse::Read => {
let data = match get_blob() {
Some(bytes) => bytes.bytes,
None => {
return Err(VfsError::ParseError {
error: "no blob".to_string(),
path: self.path.clone(),
})
}
};
Ok(data)
}
VfsResponse::Err(e) => Err(e.into()),
_ => Err(VfsError::ParseError {
error: "unexpected response".to_string(),
path: self.path.clone(),
}),
}
}
pub fn read_into(&self, buffer: &mut [u8]) -> Result<usize, VfsError> {
let message = vfs_request(&self.path, VfsAction::Read)
.send_and_await_response(self.timeout)
.unwrap()
.map_err(|e| VfsError::SendError(e.kind))?;
match parse_response(message.body())? {
VfsResponse::Read => {
let data = get_blob().unwrap_or_default().bytes;
let len = std::cmp::min(data.len(), buffer.len());
buffer[..len].copy_from_slice(&data[..len]);
Ok(len)
}
VfsResponse::Err(e) => Err(e.into()),
_ => Err(VfsError::ParseError {
error: "unexpected response".to_string(),
path: self.path.clone(),
}),
}
}
pub fn read_at(&self, buffer: &mut [u8]) -> Result<usize, VfsError> {
let length = buffer.len() as u64;
let message = vfs_request(&self.path, VfsAction::ReadExact { length })
.send_and_await_response(self.timeout)
.unwrap()
.map_err(|e| VfsError::SendError(e.kind))?;
match parse_response(message.body())? {
VfsResponse::Read => {
let data = get_blob().unwrap_or_default().bytes;
let len = std::cmp::min(data.len(), buffer.len());
buffer[..len].copy_from_slice(&data[..len]);
Ok(len)
}
VfsResponse::Err(e) => Err(e.into()),
_ => Err(VfsError::ParseError {
error: "unexpected response".to_string(),
path: self.path.clone(),
}),
}
}
pub fn read_to_end(&self) -> Result<Vec<u8>, VfsError> {
let message = vfs_request(&self.path, VfsAction::ReadToEnd)
.send_and_await_response(self.timeout)
.unwrap()
.map_err(|e| VfsError::SendError(e.kind))?;
match parse_response(message.body())? {
VfsResponse::Read => Ok(get_blob().unwrap_or_default().bytes),
VfsResponse::Err(e) => Err(e),
_ => Err(VfsError::ParseError {
error: "unexpected response".to_string(),
path: self.path.clone(),
}),
}
}
pub fn read_to_string(&self) -> Result<String, VfsError> {
let message = vfs_request(&self.path, VfsAction::ReadToString)
.send_and_await_response(self.timeout)
.unwrap()
.map_err(|e| VfsError::SendError(e.kind))?;
match parse_response(message.body())? {
VfsResponse::ReadToString(s) => Ok(s),
VfsResponse::Err(e) => Err(e),
_ => Err(VfsError::ParseError {
error: "unexpected response".to_string(),
path: self.path.clone(),
}),
}
}
pub fn write(&self, buffer: &[u8]) -> Result<(), VfsError> {
let message = vfs_request(&self.path, VfsAction::Write)
.blob_bytes(buffer)
.send_and_await_response(self.timeout)
.unwrap()
.map_err(|e| VfsError::SendError(e.kind))?;
match parse_response(message.body())? {
VfsResponse::Ok => Ok(()),
VfsResponse::Err(e) => Err(e),
_ => Err(VfsError::ParseError {
error: "unexpected response".to_string(),
path: self.path.clone(),
}),
}
}
pub fn write_all(&mut self, buffer: &[u8]) -> Result<(), VfsError> {
let message = vfs_request(&self.path, VfsAction::WriteAll)
.blob_bytes(buffer)
.send_and_await_response(self.timeout)
.unwrap()
.map_err(|e| VfsError::SendError(e.kind))?;
match parse_response(message.body())? {
VfsResponse::Ok => Ok(()),
VfsResponse::Err(e) => Err(e),
_ => Err(VfsError::ParseError {
error: "unexpected response".to_string(),
path: self.path.clone(),
}),
}
}
pub fn append(&mut self, buffer: &[u8]) -> Result<(), VfsError> {
let message = vfs_request(&self.path, VfsAction::Append)
.blob_bytes(buffer)
.send_and_await_response(self.timeout)
.unwrap()
.map_err(|e| VfsError::SendError(e.kind))?;
match parse_response(message.body())? {
VfsResponse::Ok => Ok(()),
VfsResponse::Err(e) => Err(e),
_ => Err(VfsError::ParseError {
error: "unexpected response".to_string(),
path: self.path.clone(),
}),
}
}
pub fn seek(&mut self, pos: SeekFrom) -> Result<u64, VfsError> {
let message = vfs_request(&self.path, VfsAction::Seek(pos))
.send_and_await_response(self.timeout)
.unwrap()
.map_err(|e| VfsError::SendError(e.kind))?;
match parse_response(message.body())? {
VfsResponse::SeekFrom {
new_offset: new_pos,
} => Ok(new_pos),
VfsResponse::Err(e) => Err(e),
_ => Err(VfsError::ParseError {
error: "unexpected response".to_string(),
path: self.path.clone(),
}),
}
}
pub fn copy(&mut self, path: &str) -> Result<File, VfsError> {
let message = vfs_request(
&self.path,
VfsAction::CopyFile {
new_path: path.to_string(),
},
)
.send_and_await_response(self.timeout)
.unwrap()
.map_err(|e| VfsError::SendError(e.kind))?;
match parse_response(message.body())? {
VfsResponse::Ok => Ok(File {
path: path.to_string(),
timeout: self.timeout,
}),
VfsResponse::Err(e) => Err(e),
_ => Err(VfsError::ParseError {
error: "unexpected response".to_string(),
path: self.path.clone(),
}),
}
}
pub fn set_len(&mut self, size: u64) -> Result<(), VfsError> {
let message = vfs_request(&self.path, VfsAction::SetLen(size))
.send_and_await_response(self.timeout)
.unwrap()
.map_err(|e| VfsError::SendError(e.kind))?;
match parse_response(message.body())? {
VfsResponse::Ok => Ok(()),
VfsResponse::Err(e) => Err(e),
_ => Err(VfsError::ParseError {
error: "unexpected response".to_string(),
path: self.path.clone(),
}),
}
}
pub fn metadata(&self) -> Result<FileMetadata, VfsError> {
let message = vfs_request(&self.path, VfsAction::Metadata)
.send_and_await_response(self.timeout)
.unwrap()
.map_err(|e| VfsError::SendError(e.kind))?;
match parse_response(message.body())? {
VfsResponse::Metadata(metadata) => Ok(metadata),
VfsResponse::Err(e) => Err(e),
_ => Err(VfsError::ParseError {
error: "unexpected response".to_string(),
path: self.path.clone(),
}),
}
}
pub fn sync_all(&self) -> Result<(), VfsError> {
let message = vfs_request(&self.path, VfsAction::SyncAll)
.send_and_await_response(self.timeout)
.unwrap()
.map_err(|e| VfsError::SendError(e.kind))?;
match parse_response(message.body())? {
VfsResponse::Ok => Ok(()),
VfsResponse::Err(e) => Err(e),
_ => Err(VfsError::ParseError {
error: "unexpected response".to_string(),
path: self.path.clone(),
}),
}
}
}
impl Drop for File {
fn drop(&mut self) {
vfs_request(&self.path, VfsAction::CloseFile)
.send()
.unwrap();
}
}
pub fn create_drive(
package_id: PackageId,
drive: &str,
timeout: Option<u64>,
) -> Result<String, VfsError> {
let timeout = timeout.unwrap_or(5);
let path = format!("/{}/{}", package_id, drive);
let message = vfs_request(&path, VfsAction::CreateDrive)
.send_and_await_response(timeout)
.unwrap()
.map_err(|e| VfsError::SendError(e.kind))?;
match parse_response(message.body())? {
VfsResponse::Ok => Ok(path),
VfsResponse::Err(e) => Err(e),
_ => Err(VfsError::ParseError {
error: "unexpected response".to_string(),
path,
}),
}
}
pub fn open_file(path: &str, create: bool, timeout: Option<u64>) -> Result<File, VfsError> {
let timeout = timeout.unwrap_or(5);
let message = vfs_request(path, VfsAction::OpenFile { create })
.send_and_await_response(timeout)
.unwrap()
.map_err(|e| VfsError::SendError(e.kind))?;
match parse_response(message.body())? {
VfsResponse::Ok => Ok(File {
path: path.to_string(),
timeout,
}),
VfsResponse::Err(e) => Err(e),
_ => Err(VfsError::ParseError {
error: "unexpected response".to_string(),
path: path.to_string(),
}),
}
}
pub fn create_file(path: &str, timeout: Option<u64>) -> Result<File, VfsError> {
let timeout = timeout.unwrap_or(5);
let message = vfs_request(path, VfsAction::CreateFile)
.send_and_await_response(timeout)
.unwrap()
.map_err(|e| VfsError::SendError(e.kind))?;
match parse_response(message.body())? {
VfsResponse::Ok => Ok(File {
path: path.to_string(),
timeout,
}),
VfsResponse::Err(e) => Err(e),
_ => Err(VfsError::ParseError {
error: "unexpected response".to_string(),
path: path.to_string(),
}),
}
}
pub fn remove_file(path: &str, timeout: Option<u64>) -> Result<(), VfsError> {
let timeout = timeout.unwrap_or(5);
let message = vfs_request(path, VfsAction::RemoveFile)
.send_and_await_response(timeout)
.unwrap()
.map_err(|e| VfsError::SendError(e.kind))?;
match parse_response(message.body())? {
VfsResponse::Ok => Ok(()),
VfsResponse::Err(e) => Err(e.into()),
_ => Err(VfsError::ParseError {
error: "unexpected response".to_string(),
path: path.to_string(),
}),
}
}