makepad_studio/file_system/
file_client_desktop.rs1use {
2 crate::{
3 makepad_micro_serde::*,
4 makepad_platform::*,
5 makepad_file_protocol::{FileRequest, FileClientMessage},
6 makepad_file_server::{FileServerConnection, FileServer, FileSystemRoots},
7 },
8 std::{
9 io::{Read, Write},
11 net::{ TcpStream},
12 sync::mpsc::{self, Receiver, Sender, TryRecvError},
13 thread,
14 },
15};
16
17#[derive(Default)]
18pub struct FileClient {
19pub inner: Option<FileClientInner>
22}
23
24pub struct FileClientInner {
25 pub request_sender: Sender<FileRequest>,
26 pub message_signal: SignalToUI,
27 pub message_receiver: Receiver<FileClientMessage>,
28}
29
30impl FileClient {
31 pub fn init(&mut self, _cx:&mut Cx, roots:FileSystemRoots){
32 if self.inner.is_none() {
33 self.inner = Some(FileClientInner::new_with_local_server(roots))
34 }
35 }
36
37
38 pub fn load_file_tree(&mut self) {
39 self.send_request(FileRequest::LoadFileTree {with_data: false});
40 }
41
42 pub fn load_snapshot_image(&mut self, root:&str, hash:&str) {
43 self.send_request(FileRequest::LoadSnapshotImage {root:root.to_string(), hash:hash.to_string()});
44 }
45
46 pub fn send_request(&self, request: FileRequest) {
47 self.inner.as_ref().unwrap().request_sender.send(request).unwrap();
48 }
49
50 pub fn request_sender(&mut self) -> impl FnMut(FileRequest) + '_ {
51 let request_sender = &self.inner.as_ref().unwrap().request_sender;
52 move | request | request_sender.send(request).unwrap()
53 }
54
55 pub fn poll_messages(&self)->Vec<FileClientMessage> {
56 let mut messages = Vec::new();
57 let inner = self.inner.as_ref().unwrap();
58 loop {
59 match inner.message_receiver.try_recv() {
60 Ok(message) => messages.push(message),
61 Err(TryRecvError::Empty) => break,
62 _ => panic!(),
63 }
64 }
65 messages
66 }
67}
68
69impl FileClientInner {
70 pub fn new_with_local_server(roots:FileSystemRoots) -> Self {
71 let (request_sender, request_receiver) = mpsc::channel();
72 let message_signal = SignalToUI::new();
73 let (message_sender, message_receiver) = mpsc::channel();
74
75 let mut server = FileServer::new(roots);
87 spawn_local_request_handler(
88 request_receiver,
89 server.connect(Box::new({
90 let message_sender = message_sender.clone();
91 let message_signal = message_signal.clone();
92 move | notification | {
93 message_sender.send(FileClientMessage::Notification(notification)).unwrap();
94 message_signal.set();
95 }
96 })),
97 message_signal.clone(),
98 message_sender,
99 );
100 Self {
103 request_sender,
104 message_signal,
105 message_receiver
106 }
107 }
108
109 pub fn new_connect_remote(to_server: &str) -> Self {
110 let (request_sender, request_receiver) = mpsc::channel();
111 let message_signal = SignalToUI::new();
112 let (message_sender, message_receiver) = mpsc::channel();
113
114 let stream = TcpStream::connect(to_server).unwrap();
115 spawn_request_sender(request_receiver, stream.try_clone().unwrap());
116 spawn_response_or_notification_receiver(stream, message_signal.clone(), message_sender,);
117
118 Self {
119 request_sender,
120 message_signal,
121 message_receiver
122 }
123 }
124
125}
126fn _spawn_remote_request_handler(
151 connection: FileServerConnection,
152 mut stream: TcpStream,
153 message_sender: Sender<FileClientMessage>,
154) {
155 thread::spawn(move || loop {
156 let mut len_bytes = [0; 4];
157 stream.read_exact(&mut len_bytes).unwrap();
158 let len = u32::from_be_bytes(len_bytes);
159 let mut request_bytes = vec![0; len as usize];
160 stream.read_exact(&mut request_bytes).unwrap();
161
162 let request = DeBin::deserialize_bin(request_bytes.as_slice()).unwrap();
163 let response = connection.handle_request(request);
164 message_sender.send(FileClientMessage::Response(response)).unwrap();
165 });
166}
167
168fn _spawn_response_or_notification_sender(
169 message_receiver: Receiver<FileClientMessage>,
170 mut stream: TcpStream,
171) {
172 thread::spawn(move || loop {
173 let message = message_receiver.recv().unwrap();
174 let mut message_bytes = Vec::new();
175
176 message.ser_bin(&mut message_bytes);
177
178 let len_bytes = message_bytes.len().to_be_bytes();
179 stream.write_all(&len_bytes).unwrap();
180 stream.write_all(&message_bytes).unwrap();
181 });
182}
183
184fn spawn_request_sender(request_receiver: Receiver<FileRequest>, mut stream: TcpStream) {
185 thread::spawn(move || loop {
186 let request = request_receiver.recv().unwrap();
187 let mut request_bytes = Vec::new();
188 request.ser_bin(&mut request_bytes);
189 let len_bytes = request_bytes.len().to_be_bytes();
190 stream.write_all(&len_bytes).unwrap();
191 stream.write_all(&request_bytes).unwrap();
192 });
193}
194
195fn spawn_response_or_notification_receiver(
196 mut stream: TcpStream,
197 message_signal: SignalToUI,
198 message_sender: Sender<FileClientMessage>,
199) {
200 thread::spawn(move || loop {
201 let mut len_bytes = [0; 4];
202 stream.read_exact(&mut len_bytes).unwrap();
203
204 let len = u32::from_be_bytes(len_bytes);
205 let mut action_bytes = vec![0; len as usize];
206 stream.read_exact(&mut action_bytes).unwrap();
207 let action = DeBin::deserialize_bin(action_bytes.as_slice()).unwrap();
208 message_sender.send(action).unwrap();
209 message_signal.set()
210 });
211}
212
213fn spawn_local_request_handler(
214 request_receiver: Receiver<FileRequest>,
215 connection: FileServerConnection,
216 action_signal: SignalToUI,
217 action_sender: Sender<FileClientMessage>,
218) {
219 thread::spawn(move || loop {
220 if let Ok(request) = request_receiver.recv(){
221 let response = connection.handle_request(request);
222 action_sender.send(FileClientMessage::Response(response)).unwrap();
223 action_signal.set()
224 }
225 });
226}