linux_tuples_client/
lib.rs

1
2use std::net::*;
3use std::io::prelude::*;
4use std::mem::*;
5use std::vec::Vec;
6
7
8/// Enum, which is used to contain LinuxTuples element
9#[derive(Clone, PartialEq)]
10pub enum E {
11    I(i32),
12    D(f64),
13    S(String),
14    T(Vec<E>),
15    None,
16}
17
18impl E {
19	/// Prints an element to the standard output
20	/// # Examples
21	///
22	/// ```
23	/// # e.print()
24	/// ```
25	pub fn print(&self) {
26		match self {
27			&E::I(ref i) => print!("Int: {}, ", i),
28			&E::D(ref d) => print!("Double: {}, ", d),
29			&E::S(ref s) => print!("String: {}, ", s),
30			&E::T(ref v) => {
31				print!("Tuple: [");
32				for e in v {
33					e.print();
34				}
35				print!("], ");
36				
37			}
38			&E::None => println!("Wildcard"),
39		}
40	}
41}
42
43/// Used to connect to LinuxTuples server
44///
45/// # Examples
46///
47/// ```
48/// let conn = LinuxTuplesConnection { addr };
49/// ``` 
50#[derive(Clone)]
51pub struct LinuxTuplesConnection {
52	pub connection: SocketAddr,
53}
54
55
56const PUT: i32 = 0;
57const GET: i32 = 1;
58const READ: i32 = 2;
59const GET_NB: i32 = 3;
60const READ_NB: i32 = 4;
61const DUMP: i32 = 5;
62const COUNT: i32 = 6;
63const REPLACE: i32 = 8;
64const LOG: i32 = 7;
65
66const ASCII_S: i32 = 115;
67const ASCII_I: i32 = 105;
68const ASCII_D: i32 = 100;
69const ASCII_Q: i32 = 63;
70const ASCII_T: i32 = 116;
71
72fn ti(i: i32) -> [u8; 4] {
73	let buff: [u8; 4];
74	unsafe {
75		buff = transmute(i);
76	}
77	return buff;
78} 
79
80fn ctoi(arr: &mut [u8; 24], mut val: i32, offset: isize) {
81	unsafe {
82		::std::ptr::copy_nonoverlapping(&mut val as *mut _ as *mut u8, arr.as_ptr().offset(offset) as *mut u8, ::std::mem::size_of::<i32>());
83	}
84}
85
86fn ciot(arr:&[u8; 24], offset:isize) -> i32 {
87	let mut val: i32 = 0;
88	
89	unsafe {
90		::std::ptr::copy_nonoverlapping(arr.as_ptr().offset(offset) as *mut u8, &mut val as *mut _ as *mut u8, ::std::mem::size_of::<i32>());
91	}
92	
93	return val;
94}
95
96fn cdot(arr:&[u8; 24], offset:isize) -> f64 {
97	let mut val: f64 = 0.;
98	unsafe {
99		::std::ptr::copy_nonoverlapping(arr.as_ptr().offset(offset) as *mut u8, &mut val as *mut _ as *mut u8, ::std::mem::size_of::<f64>());
100	}
101	return val;
102}
103
104fn ctod(arr: &mut [u8; 24], mut val: f64, offset: isize) {
105	unsafe {
106		::std::ptr::copy_nonoverlapping(&mut val as *mut _ as *mut u8, arr.as_ptr().offset(offset) as *mut u8, ::std::mem::size_of::<f64>());
107	}
108}  
109
110fn send_tuple(tuple: &Vec<E>, stream: &mut TcpStream) {
111	
112    stream.write_all(& (ti(tuple.len() as i32)));
113    
114    let mut string_length:i32 = 0;
115    
116    for elem in tuple {
117    	match elem {
118    		&E::S(ref s) => string_length += s.len() as i32,
119    		_ => {}
120    	}
121    }
122    
123    stream.write_all(&ti(string_length));
124    
125    string_length = 0;
126    
127    let mut buff: [u8; 24] = [0; 24];
128    
129    for elem in tuple {
130    	match elem {
131    		&E::I(ref i) => {
132				//tag
133   	 			ctoi(&mut buff, ASCII_I, 0);
134   	 			//union
135   	 			ctoi(&mut buff, *i, 8);
136   	 			
137   	 			stream.write_all(&buff); 
138    		},
139    		&E::D(ref d) => {
140    			//tag
141   	 			ctoi(&mut buff, ASCII_D, 0);
142   	 			//union
143   	 			ctod(&mut buff, *d, 8);
144   	 			stream.write_all(&buff);
145   	 			
146    		},
147    		&E::S(ref s) => {
148    			//tag
149   	 			ctoi(&mut buff, ASCII_S, 0);
150   	 			
151   	 			//union
152   	 			ctoi(&mut buff, string_length, 8);
153   	 			ctoi(&mut buff, s.len() as i32, 16);
154   	 			
155   	 			//tuple pointer
156   	 			stream.write_all(&buff);
157   	 			
158   	 			string_length += s.len() as i32;
159    		},
160    		&E::T(ref v) => {
161    			ctoi(&mut buff, ASCII_T, 0);
162    			
163    			stream.write_all(&mut buff);
164    			
165    			send_tuple(v, stream);
166    		}
167    		&E::None => {
168    			ctoi(&mut buff, ASCII_Q, 0);
169    			
170    			stream.write_all(&buff);
171    		}
172    	}
173    }
174    
175    for elem in tuple {
176    	match elem {
177    		&E::S(ref s) => {
178    			stream.write_all(s.as_bytes());
179    		}
180    		_ => {}
181    	}
182    }
183}
184
185fn recv_tuple(stream: &mut TcpStream) -> Vec<E> {
186	
187	struct str_desc {
188		used: bool,
189		offset: i32,
190		len: i32,
191	}
192	
193	let mut tuple: Vec<E> = Vec::<E>::new();
194	let mut str_descs: Vec<str_desc> = Vec::<str_desc>::new();
195	
196	let mut buff_4:[u8; 4] = [0; 4];
197	let mut buff_8:[u8; 8] = [0; 8];
198	let mut buff:[u8; 24] = [0; 24];
199	
200	stream.read_exact(&mut buff_4);
201	let num_elements:i32 = unsafe { transmute(buff_4) };
202	
203	//non-blocking reads/writes
204	if num_elements == -1 {
205		return tuple;
206	}
207	
208	stream.read_exact(&mut buff_4);
209	let string_length:i32 = unsafe { transmute(buff_4) };
210	
211	for i in 0..num_elements {
212		
213		stream.read_exact(&mut buff);
214		
215		let tag: i32 = ciot(&buff, 0);
216		
217		match tag {
218			ASCII_I => {
219				tuple.push(E::I(ciot(&buff, 8)));
220				str_descs.push(str_desc { used: false, offset: 0, len: 0} );
221			},
222			ASCII_D => {
223				tuple.push(E::D(cdot(&buff, 8)));
224				str_descs.push(str_desc { used: false, offset: 0, len: 0} );
225			},
226			ASCII_S => {
227				str_descs.push(str_desc { 
228						used: true,
229						offset: ciot(&buff, 8),
230						len: ciot(&buff, 16),
231					});
232				tuple.push(E::S("".to_string()));
233			},
234			ASCII_T => {
235				str_descs.push(str_desc { used: false, offset: 0, len: 0 });
236				tuple.push(E::T(recv_tuple(stream)));
237			}
238			ASCII_Q => {
239				str_descs.push(str_desc { used: false, offset: 0, len: 0} );
240			},
241			_ => {
242				
243			}
244		}
245	}
246	
247	if string_length != 0 {
248		let mut string_space:Vec<u8> = vec![0; string_length as usize];
249		stream.read_exact(&mut string_space);
250		
251		let mut str_slice = string_space.as_slice();
252		for i in 0..num_elements {
253			if str_descs[i as usize].used == true {
254				tuple[i as usize] = E::S(String::from_utf8(
255					string_space[
256						(str_descs[i as usize].offset as usize)..
257						(str_descs[i as usize].offset + str_descs[i as usize].len) as usize].to_vec()).unwrap());
258			}
259		}
260		
261	}
262	
263	return tuple;
264}
265
266impl LinuxTuplesConnection {
267	/// Puts tuple to the tuple space
268	///
269	/// # Examples
270	///
271	/// ```
272	/// conn.put_tuple(&vec![E::I(123), E::S("123".to_string())]);
273	/// ```
274	///
275	/// # Errors
276	///
277	/// Returns Err if disconnected, or incorrect data arrived
278	pub fn put_tuple(&self, tuple: &Vec<E>) -> std::io::Result<bool> {
279	    let mut stream_err = TcpStream::connect(&self.connection);
280	    match stream_err {
281	    	Ok(mut stream) => {
282	    		stream.write_all(&ti(PUT));
283				send_tuple(tuple, &mut stream);
284				stream.shutdown(Shutdown::Write);
285				return Ok(true);
286	    	}
287	    	Err(why) => {
288	    		return Err(why);
289	    	}
290	    }
291	}
292	
293	/// Gets tuple from the tuple space
294	///
295	/// # Examples
296	///
297	/// ```
298	/// let tuple = conn.get_tuple(&vec![E::I(123), E::None]).unwrap();
299	/// ```
300	/// 
301	/// # Errors
302	///
303	/// Returns Err if disconnected, or incorrect data arrived
304	pub fn get_tuple(&self, tuple: &Vec<E>) -> std::io::Result<Vec<E>>
305	{
306		let mut stream_err = TcpStream::connect(&self.connection);
307		match stream_err {
308			Ok(mut stream) => {
309				stream.write_all(&ti(GET));
310				
311				send_tuple(tuple, &mut stream);
312				
313				stream.shutdown(Shutdown::Write);
314				
315				return Ok(recv_tuple(&mut stream));
316			}
317			Err(why) => {
318				return Err(why);
319			}
320		}
321	}
322	
323	/// Reads tuple from the tuple space
324	///
325	/// # Examples
326	///
327	/// ```
328	/// let tuple = conn.read_tuple(&vec![E::I(123), E::None]).unwrap();
329	/// ```
330	/// # Errors
331	///
332	/// Returns Err if disconnected, or incorrect data arrived
333	pub fn read_tuple(&self, tuple: &Vec<E>) -> std::io::Result<Vec<E>>
334	{
335		let mut stream_err = TcpStream::connect(&self.connection);
336		match stream_err {
337			Ok(mut stream) => {
338				stream.write_all(&ti(READ));
339				
340				send_tuple(tuple, &mut stream);
341				
342				stream.shutdown(Shutdown::Write);
343				
344				return Ok(recv_tuple(&mut stream));
345			}
346			Err(why) => {
347				return Err(why);
348			}
349		}
350	}
351	
352	/// Gets tuple from the tuple space; non-blocking
353	///
354	/// If nothing found, returns empty vector.
355	/// # Examples
356	///
357	/// ```
358	/// let tuple = conn.get_nb_tuple(&vec![E::I(123), E::S("123".to_string())]).unwrap();
359	/// ```
360	///
361	/// # Errors
362	///
363	/// Returns Err if disconnected, or incorrect data arrived
364	pub fn get_nb_tuple(&self, tuple: &Vec<E>) -> std::io::Result<Vec<E>>
365	{
366		let mut stream_err = TcpStream::connect(&self.connection);
367		match stream_err {
368			Ok(mut stream) => {
369				stream.write_all(&ti(GET_NB));
370				
371				send_tuple(tuple, &mut stream);
372				
373				stream.shutdown(Shutdown::Write);
374				
375				return Ok(recv_tuple(&mut stream));
376			}
377			Err(why) => {
378				return Err(why);
379			}
380		}
381	}
382	
383	/// Reads tuple from the tuple space; non-blocking
384	///
385	/// If nothing found, returns empty vector.
386	///
387	/// # Examples
388	///
389	/// ```
390	/// let tuple = conn.read_nb_tuple(&vec![E::I(123), E::S("123".to_string())]).unwrap();
391	/// ```
392	///
393	/// # Errors
394	///
395	/// Returns Err if disconnected, or incorrect data arrived
396	pub fn read_nb_tuple(&self, tuple: &Vec<E>) -> std::io::Result<Vec<E>>
397	{
398		let mut stream_err = TcpStream::connect(&self.connection);
399		match stream_err {
400			Ok(mut stream) => {
401				stream.write_all(&ti(READ_NB));
402				
403				send_tuple(tuple, &mut stream);
404				
405				stream.shutdown(Shutdown::Write);
406				
407				return Ok(recv_tuple(&mut stream));
408			}
409			Err(why) => {
410				return Err(why);
411			}
412		}
413	}
414	
415	/// Reads all tuples from the tuple space that satisfy templates
416	///
417	/// If nothing found, returns empty vector. If template list is empty, returns all tuples in the space.
418	///
419	/// # Examples
420	///
421	/// ```
422	/// let tuple_list = conn.read_all_tuples(&vec![vec![E::I(123), E::None], vec![E::S("123".to_string()), E::None]]).unwrap();
423	/// ```
424	///
425	/// # Errors
426	///
427	/// Returns Err if disconnected, or incorrect data arrived
428	pub fn read_all_tuples(&self, tuples: &Vec<Vec<E>>) -> std::io::Result<Vec<Vec<E>>>
429	{
430		let mut stream_err = TcpStream::connect(&self.connection);
431		match stream_err {
432			Ok(mut stream) => {
433				stream.write_all(&ti(DUMP));
434				let count: i32 = tuples.len() as i32;
435				stream.write_all(&ti(count));
436				
437				for tuple in tuples {
438					send_tuple(tuple, &mut stream);
439				}
440				
441				let mut buff_4:[u8; 4] = [0; 4];
442				
443				stream.read_exact(&mut buff_4);
444				
445				let recv_count = unsafe { transmute(buff_4) };
446				
447				let mut result:Vec<Vec<E>> = Vec::<Vec<E>>::new();
448				
449				for i in 0..recv_count {
450					result.push(recv_tuple(&mut stream));
451				}
452				return Ok(result);
453			}
454			Err(why) => {
455				return Err(why);
456			}
457		}
458	}
459	
460	/// Calculates a number tuples from the tuple space that satisfy templates
461	///
462	/// If nothing found, 0. If template list is empty, returns number of all tuples in the space.
463	///
464	/// # Examples
465	///
466	/// ```
467	/// let count = conn.number_of_tuples(&vec![vec![E::I(123), E::None], vec![E::S("123".to_string()), E::None]]).unwrap();
468	/// ```
469	///
470	/// # Errors
471	///
472	/// Returns Err if disconnected, or incorrect data arrived
473	pub fn number_of_tuples(&self, tuples: &Vec<Vec<E>>) -> std::io::Result<i32>
474	{
475		let mut stream_err = TcpStream::connect(&self.connection);
476		match stream_err {
477			Ok(mut stream) => {
478				stream.write_all(&ti(COUNT));
479				let count: i32 = tuples.len() as i32;
480				stream.write_all(&ti(count));
481				
482				for tuple in tuples {
483					send_tuple(tuple, &mut stream);
484				}
485				
486				let mut buff_4:[u8; 4] = [0; 4];
487				
488				stream.read_exact(&mut buff_4);
489				
490				let recv_count = unsafe { transmute(buff_4) };
491				
492				return Ok(recv_count);
493			}
494			Err(why) => {
495				return Err(why);
496			}
497		}
498	}
499	
500	/// Replaces one tuple with another in the space
501	///
502	///
503	/// # Examples
504	///
505	/// ```
506	/// conn.replace_tuple(&vec![E::I(123)], &vec![E::S("123".to_string())]).unwrap();
507	/// ```
508	///
509	/// # Errors
510	///
511	/// Returns Err if source tuple wasn't found or data was corrupted/socket disconnected.
512	pub fn replace_tuple(&self, tuple: &Vec<E>, replacement: &Vec<E>) -> std::io::Result<bool> {
513			let mut stream_err = TcpStream::connect(&self.connection);
514			match stream_err {
515				Ok(mut stream) => {
516					stream.write_all(&ti(REPLACE));
517					send_tuple(tuple, &mut stream);
518					send_tuple(replacement, &mut stream);
519					let mut buff_4:[u8; 4] = [0; 4];
520					stream.read_exact(&mut buff_4);
521					
522					let op:i32 = unsafe { transmute(buff_4) };
523					if op != REPLACE {
524						return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Replace failed"));
525					} else {
526						return Ok(true);
527					}
528				}
529				Err(why) => {
530					return Err(why);
531					
532				}
533			}
534	}
535	/// Returns a list of operations done to a tuple.
536	///
537	/// # Examples
538	///
539	/// ```
540	/// let log = conn.server_log();
541	/// ```
542	/// # Errors
543	///
544	/// Returns Err if disconnected, or incorrect data arrived
545	pub fn server_log(&self) -> std::io::Result<String> {
546		let mut stream_err = TcpStream::connect(&self.connection);
547		match stream_err {
548			Ok(mut stream) => {
549				stream.write_all(&ti(LOG));
550				let mut log:String = "".to_string();
551				stream.read_to_string(&mut log);
552				return Ok(log);
553			}
554			Err(why) => {
555				return Err(why);
556			}
557		}
558	}
559	
560	
561	///Prints a tuple to the standard output
562	///
563	/// # Examples
564	/// ```
565	/// LinuxTuplesConnection::print_tuple(&vec![E::I(123)]);
566	/// ```
567	pub fn print_tuple(tuple: &Vec<E>) {
568				print!("Tuple: [");
569				for e in tuple {
570					e.print();
571				}
572				print!("], ");
573	}
574}