1use super::{Buffer, Completion, File, MemoryIO, OpenFlags, IO};
2use crate::ext::VfsMod;
3use crate::io::clock::{Clock, Instant};
4use crate::{LimboError, Result};
5use limbo_ext::{VfsFileImpl, VfsImpl};
6use std::cell::RefCell;
7use std::ffi::{c_void, CString};
8use std::sync::Arc;
9
10impl Clock for VfsMod {
11 fn now(&self) -> Instant {
12 let now = chrono::Local::now();
13 Instant {
14 secs: now.timestamp(),
15 micros: now.timestamp_subsec_micros(),
16 }
17 }
18}
19
20impl IO for VfsMod {
21 fn open_file(&self, path: &str, flags: OpenFlags, direct: bool) -> Result<Arc<dyn File>> {
22 let c_path = CString::new(path).map_err(|_| {
23 LimboError::ExtensionError("Failed to convert path to CString".to_string())
24 })?;
25 let ctx = self.ctx as *mut c_void;
26 let vfs = unsafe { &*self.ctx };
27 let file = unsafe { (vfs.open)(ctx, c_path.as_ptr(), flags.0, direct) };
28 if file.is_null() {
29 return Err(LimboError::ExtensionError("File not found".to_string()));
30 }
31 Ok(Arc::new(limbo_ext::VfsFileImpl::new(file, self.ctx)?))
32 }
33
34 fn run_once(&self) -> Result<()> {
35 if self.ctx.is_null() {
36 return Err(LimboError::ExtensionError("VFS is null".to_string()));
37 }
38 let vfs = unsafe { &*self.ctx };
39 let result = unsafe { (vfs.run_once)(vfs.vfs) };
40 if !result.is_ok() {
41 return Err(LimboError::ExtensionError(result.to_string()));
42 }
43 Ok(())
44 }
45
46 fn wait_for_completion(&self, _c: Arc<Completion>) -> Result<()> {
47 todo!();
48 }
49
50 fn generate_random_number(&self) -> i64 {
51 if self.ctx.is_null() {
52 return -1;
53 }
54 let vfs = unsafe { &*self.ctx };
55 unsafe { (vfs.gen_random_number)() }
56 }
57
58 fn get_memory_io(&self) -> Arc<MemoryIO> {
59 Arc::new(MemoryIO::new())
60 }
61}
62
63impl VfsMod {
64 #[allow(dead_code)] fn get_current_time(&self) -> String {
66 if self.ctx.is_null() {
67 return "".to_string();
68 }
69 unsafe {
70 let vfs = &*self.ctx;
71 let chars = (vfs.current_time)();
72 let cstr = CString::from_raw(chars as *mut _);
73 cstr.to_string_lossy().into_owned()
74 }
75 }
76}
77
78impl File for VfsFileImpl {
79 fn lock_file(&self, exclusive: bool) -> Result<()> {
80 let vfs = unsafe { &*self.vfs };
81 let result = unsafe { (vfs.lock)(self.file, exclusive) };
82 if result.is_ok() {
83 return Err(LimboError::ExtensionError(result.to_string()));
84 }
85 Ok(())
86 }
87
88 fn unlock_file(&self) -> Result<()> {
89 if self.vfs.is_null() {
90 return Err(LimboError::ExtensionError("VFS is null".to_string()));
91 }
92 let vfs = unsafe { &*self.vfs };
93 let result = unsafe { (vfs.unlock)(self.file) };
94 if result.is_ok() {
95 return Err(LimboError::ExtensionError(result.to_string()));
96 }
97 Ok(())
98 }
99
100 fn pread(&self, pos: usize, c: Arc<Completion>) -> Result<()> {
101 let r = match &*c {
102 Completion::Read(ref r) => r,
103 _ => unreachable!(),
104 };
105 let result = {
106 let mut buf = r.buf_mut();
107 let count = buf.len();
108 let vfs = unsafe { &*self.vfs };
109 unsafe { (vfs.read)(self.file, buf.as_mut_ptr(), count, pos as i64) }
110 };
111 if result < 0 {
112 Err(LimboError::ExtensionError("pread failed".to_string()))
113 } else {
114 c.complete(result);
115 Ok(())
116 }
117 }
118
119 fn pwrite(&self, pos: usize, buffer: Arc<RefCell<Buffer>>, c: Arc<Completion>) -> Result<()> {
120 let buf = buffer.borrow();
121 let count = buf.as_slice().len();
122 if self.vfs.is_null() {
123 return Err(LimboError::ExtensionError("VFS is null".to_string()));
124 }
125 let vfs = unsafe { &*self.vfs };
126 let result = unsafe {
127 (vfs.write)(
128 self.file,
129 buf.as_slice().as_ptr() as *mut u8,
130 count,
131 pos as i64,
132 )
133 };
134
135 if result < 0 {
136 Err(LimboError::ExtensionError("pwrite failed".to_string()))
137 } else {
138 c.complete(result);
139 Ok(())
140 }
141 }
142
143 fn sync(&self, c: Arc<Completion>) -> Result<()> {
144 let vfs = unsafe { &*self.vfs };
145 let result = unsafe { (vfs.sync)(self.file) };
146 if result < 0 {
147 Err(LimboError::ExtensionError("sync failed".to_string()))
148 } else {
149 c.complete(0);
150 Ok(())
151 }
152 }
153
154 fn size(&self) -> Result<u64> {
155 let vfs = unsafe { &*self.vfs };
156 let result = unsafe { (vfs.size)(self.file) };
157 if result < 0 {
158 Err(LimboError::ExtensionError("size failed".to_string()))
159 } else {
160 Ok(result as u64)
161 }
162 }
163
164 fn truncate(&self, _len: usize, c: Arc<Completion>) -> Result<()> {
165 c.complete(0);
169 Ok(())
170 }
171}
172
173impl Drop for VfsMod {
174 fn drop(&mut self) {
175 if self.ctx.is_null() {
176 return;
177 }
178 unsafe {
179 let _ = Box::from_raw(self.ctx as *mut VfsImpl);
180 }
181 }
182}