Skip to main content

rumtk_core/
lib.rs

1/*
2 * rumtk attempts to implement HL7 and medical protocols for interoperability in medicine.
3 * This toolkit aims to be reliable, simple, performant, and standards compliant.
4 * Copyright (C) 2024  Luis M. Santos, M.D. <lsantos@medicalmasses.com>
5 * Copyright (C) 2025  MedicalMasses L.L.C. <contact@medicalmasses.com>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19 */
20
21//#![feature(unboxed_closures)]
22//#![feature(inherent_associated_types)]
23#![feature(type_alias_impl_trait)]
24#![feature(unboxed_closures)]
25#![feature(buf_read_has_data_left)]
26#![feature(mapped_lock_guards)]
27#![feature(str_as_str)]
28
29pub mod cache;
30pub mod cli;
31pub mod core;
32pub mod dependencies;
33pub mod hash;
34pub mod id;
35pub mod json;
36pub mod log;
37pub mod maths;
38pub mod net;
39pub mod pipelines;
40pub mod scripting;
41pub mod search;
42pub mod strings;
43pub mod threading;
44pub mod types;
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49    use crate::cache::RUMCache;
50    use crate::core::{clamp_index, RUMResult};
51    use crate::search::rumtk_search::*;
52    use crate::strings::{
53        rumtk_format, AsStr, RUMArrayConversions, RUMString, RUMStringConversions, StringUtils,
54    };
55    use crate::types::{RUMDeserialize, RUMDeserializer, RUMSerialize, RUMSerializer};
56    use compact_str::CompactString;
57    use serde_json::to_string;
58    use std::process::Stdio;
59    use std::sync::Arc;
60    use tokio::sync::RwLock;
61
62    #[test]
63    fn test_is_escaped_str() {
64        let input = "\r\n\'\\\"";
65        let expected = false;
66        let result = strings::is_escaped_str(input);
67        println!("Input: {} Expected: {} Got: {}", input, expected, result);
68        assert_eq!(
69            expected, result,
70            "Incorrect detection of unescaped string as escaped!!"
71        );
72        println!("Passed!")
73    }
74
75    #[test]
76    fn test_escaping_control() {
77        let input = "\r\n\'\"\\";
78        let expected = "\\r\\n\\'\\\"\\\\";
79        let result = strings::escape(input);
80        println!(
81            "Input: {} Expected: {} Got: {}",
82            input,
83            expected,
84            result.as_str()
85        );
86        assert_eq!(expected, result, "Incorrect string escaping!");
87        println!("Passed!")
88    }
89
90    #[test]
91    fn test_escaping_unicode() {
92        let input = "❤";
93        let expected = "\\u2764";
94        let result = strings::escape(input);
95        println!(
96            "Input: {} Expected: {} Got: {}",
97            input,
98            expected,
99            result.as_str()
100        );
101        assert_eq!(expected, result, "Incorrect string escaping!");
102        println!("Passed!")
103    }
104
105    #[test]
106    fn test_unescaping_unicode() {
107        let input = "❤";
108        let escaped = strings::escape(input);
109        let expected = "❤";
110        let result = RUMString::from_utf8(strings::unescape(escaped.as_str()).unwrap()).unwrap();
111        println!(
112            "Input: {} Expected: {} Got: {}",
113            input,
114            expected,
115            result.as_str()
116        );
117        assert_eq!(expected, result.as_str(), "Incorrect string unescaping!");
118        println!("Passed!")
119    }
120
121    #[test]
122    fn test_unescaping_string() {
123        let input = "I \\u2764 my wife!";
124        let expected = "I ❤ my wife!";
125        let result = strings::unescape_string(input).unwrap();
126        println!(
127            "Input: {} Expected: {} Got: {}",
128            input,
129            expected,
130            result.as_str()
131        );
132        assert_eq!(expected, result.as_str(), "Incorrect string unescaping!");
133        println!("Passed!")
134    }
135
136    #[test]
137    fn test_is_escaped_string() {
138        let input = "I \\u2764 my wife!";
139        let expected = true;
140        let result = strings::is_escaped_str(input);
141        println!("Input: {} Expected: {} Got: {}", input, expected, result);
142        assert_eq!(
143            expected, result,
144            "Escaped string detected as unescaped string!"
145        );
146        println!("Passed!")
147    }
148
149    #[test]
150    fn test_is_unescaped_string() {
151        let input = "I ❤ my wife!";
152        let expected = false;
153        let result = strings::is_escaped_str(input);
154        println!("Input: {} Expected: {} Got: {}", input, expected, result);
155        assert_eq!(
156            expected, result,
157            "Unescaped string detected as escaped string!"
158        );
159        println!("Passed!")
160    }
161
162    #[test]
163    fn test_unique_string() {
164        let input = "I❤mywife!";
165        assert!(
166            input.as_grapheme_str().is_unique(),
167            "String was not detected as unique."
168        );
169    }
170
171    #[test]
172    fn test_non_unique_string() {
173        let input = "I❤❤mywife!";
174        assert!(
175            !input.as_grapheme_str().is_unique(),
176            "String was detected as unique."
177        );
178    }
179
180    #[test]
181    fn test_escaping_string() {
182        let input = "I ❤ my wife!";
183        let expected = "I \\u2764 my wife!";
184        let result = strings::escape(input);
185        println!(
186            "Input: {} Expected: {} Got: {}",
187            input,
188            expected,
189            result.as_str()
190        );
191        assert_eq!(expected, result.as_str(), "Incorrect string escaping!");
192        println!("Passed!")
193    }
194
195    #[test]
196    fn test_autodecode_utf8() {
197        let input = "I ❤ my wife!";
198        let result = strings::try_decode(input.as_bytes());
199        println!(
200            "Input: {} Expected: {} Got: {}",
201            input,
202            input,
203            result.as_str()
204        );
205        assert_eq!(input, result, "Incorrect string decoding!");
206        println!("Passed!")
207    }
208
209    #[test]
210    fn test_autodecode_other() {
211        //TODO: Need an example of other encoding texts.
212        let input = "I ❤ my wife!";
213        let result = input;
214        println!("Input: {} Expected: {} Got: {}", input, input, result);
215        assert_eq!(input, result, "Incorrect string decoding!");
216        println!("Passed!")
217    }
218
219    #[test]
220    fn test_decode() {
221        let input = "I ❤ my wife!";
222        let result = strings::try_decode_with(input.as_bytes(), "utf-8");
223        println!(
224            "Input: {} Expected: {} Got: {}",
225            input,
226            input,
227            result.as_str()
228        );
229        assert_eq!(input, result, "Incorrect string decoding!");
230        println!("Passed!")
231    }
232
233    #[test]
234    fn test_rumcache_insertion() {
235        let mut cache: RUMCache<&str, CompactString> = RUMCache::with_capacity(5);
236        cache.insert("❤", CompactString::from("I ❤ my wife!"));
237        println!("Contents: {:#?}", &cache);
238        assert_eq!(cache.len(), 1, "Incorrect number of items in cache!");
239        println!("Passed!")
240    }
241
242    #[test]
243    fn test_search_string_letters() {
244        let input = "Hello World!";
245        let expr = r"\w";
246        let result = string_search(input, expr, "").unwrap();
247        let expected: RUMString = RUMString::from("HelloWorld");
248        println!(
249            "Input: {:?} Expected: {:?} Got: {:?}",
250            input, expected, result
251        );
252        assert_eq!(expected, result, "String search results mismatch");
253        println!("Passed!")
254    }
255
256    #[test]
257    fn test_search_string_words() {
258        let input = "Hello World!";
259        let expr = r"\w+";
260        let result = string_search(input, expr, " ").unwrap();
261        let expected: RUMString = RUMString::from("Hello World");
262        println!(
263            "Input: {:?} Expected: {:?} Got: {:?}",
264            input, expected, result
265        );
266        assert_eq!(expected, result, "String search results mismatch");
267        println!("Passed!")
268    }
269
270    #[test]
271    fn test_search_string_named_groups() {
272        let input = "Hello World!";
273        let expr = r"(?<hello>\w{5}) (?<world>\w{5})";
274        let result = string_search_named_captures(input, expr, "").unwrap();
275        let expected: RUMString = RUMString::from("World");
276        println!(
277            "Input: {:?} Expected: {:?} Got: {:?}",
278            input, expected, result
279        );
280        assert_eq!(expected, result["world"], "String search results mismatch");
281        println!("Passed!")
282    }
283
284    #[test]
285    fn test_search_string_all_groups() {
286        let input = "Hello World!";
287        let expr = r"(?<hello>\w{5}) (?<world>\w{5})";
288        let result = string_search_all_captures(input, expr, "").unwrap();
289        let expected: Vec<&str> = vec!["Hello", "World"];
290        println!(
291            "Input: {:?} Expected: {:?} Got: {:?}",
292            input, expected, result
293        );
294        assert_eq!(expected, result, "String search results mismatch");
295        println!("Passed!")
296    }
297
298    ///////////////////////////////////Threading Tests/////////////////////////////////////////////////
299    #[test]
300    fn test_default_num_threads() {
301        use num_cpus;
302        let threads = threading::threading_functions::get_default_system_thread_count();
303        assert_eq!(
304            threads >= num_cpus::get(),
305            true,
306            "Default thread count is incorrect! We got {}, but expected {}!",
307            threads,
308            num_cpus::get()
309        );
310    }
311
312    #[test]
313    fn test_execute_job() {
314        let expected = vec![1, 2, 3];
315        let task_processor = async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<i32>> {
316            let owned_args = Arc::clone(args);
317            let lock_future = owned_args.read();
318            let locked_args = lock_future.await;
319            let mut results = TaskItems::<i32>::with_capacity(locked_args.len());
320            print!("Contents: ");
321            for arg in locked_args.iter() {
322                results.push(arg.clone());
323                println!("{} ", &arg);
324            }
325            Ok(results)
326        };
327        let locked_args = RwLock::new(expected.clone());
328        let task_args = SafeTaskArgs::<i32>::new(locked_args);
329        let task_result = rumtk_wait_on_task!(task_processor, &task_args);
330        let result = task_result.unwrap();
331        assert_eq!(&result, &expected, "{}", rumtk_format!("Task processing returned a different result than expected! Expected {:?} \nResults {:?}", &expected, &result));
332    }
333
334    #[test]
335    fn test_execute_job_macros() {
336        let expected = vec![1, 2, 3];
337        let task_processor = async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<i32>> {
338            let owned_args = Arc::clone(args);
339            let lock_future = owned_args.read();
340            let locked_args = lock_future.await;
341            let mut results = TaskItems::<i32>::with_capacity(locked_args.len());
342            print!("Contents: ");
343            for arg in locked_args.iter() {
344                results.push(arg.clone());
345                println!("{} ", &arg);
346            }
347            Ok(results)
348        };
349        let task_args = rumtk_create_task_args!(1, 2, 3);
350        let task_result = rumtk_wait_on_task!(task_processor, &task_args);
351        let result = task_result.unwrap();
352        assert_eq!(&result, &expected, "{}", rumtk_format!("Task processing returned a different result than expected! Expected {:?} \nResults {:?}", &expected, &result));
353    }
354
355    #[test]
356    fn test_execute_job_macros_one_line() {
357        let expected = vec![1, 2, 3];
358        let result = rumtk_exec_task!(
359            async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<i32>> {
360                let owned_args = Arc::clone(args);
361                let lock_future = owned_args.read();
362                let locked_args = lock_future.await;
363                let mut results = TaskItems::<i32>::with_capacity(locked_args.len());
364                print!("Contents: ");
365                for arg in locked_args.iter() {
366                    results.push(arg.clone());
367                    println!("{} ", &arg);
368                }
369                Ok(results)
370            },
371            vec![1, 2, 3]
372        )
373        .unwrap();
374        assert_eq!(&result, &expected, "{}", rumtk_format!("Task processing returned a different result than expected! Expected {:?} \nResults {:?}", &expected, &result));
375    }
376
377    #[test]
378    fn test_clamp_index_positive_index() {
379        let values = vec![1, 2, 3, 4];
380        let given_index = 3isize;
381        let max_size = values.len() as isize;
382        let index = clamp_index(&given_index, &max_size).unwrap();
383        assert_eq!(
384            index, 3,
385            "Index mismatch! Requested index {} but got {}",
386            &given_index, &index
387        );
388        assert_eq!(
389            values[index], 4,
390            "Value mismatch! Expected {} but got {}",
391            &values[3], &values[index]
392        );
393    }
394
395    #[test]
396    fn test_clamp_index_reverse_index() {
397        let values = vec![1, 2, 3, 4];
398        let given_index = -1isize;
399        let max_size = values.len() as isize;
400        let index = clamp_index(&given_index, &max_size).unwrap();
401        assert_eq!(
402            index, 4,
403            "Index mismatch! Requested index {} but got {}",
404            &given_index, &index
405        );
406        assert_eq!(
407            values[index - 1],
408            4,
409            "Value mismatch! Expected {} but got {}",
410            &values[3],
411            &values[index]
412        );
413    }
414
415    #[test]
416    fn test_block_on_task() {
417        let expect = 5;
418        let value = block_on_task(async move { 5 });
419        assert_eq!(
420            value, 5,
421            "Value mismatch from async task! Expected {} but got {}",
422            &expect, &value
423        );
424    }
425
426    ///////////////////////////////////Queue Tests/////////////////////////////////////////////////
427    use crate::cli::cli_utils::print_license_notice;
428    use crate::net::tcp::LOCALHOST;
429    use crate::pipelines::pipeline_functions::{
430        pipeline_generate_command, pipeline_pipe_processes, pipeline_spawn_process,
431    };
432    use crate::pipelines::pipeline_types::RUMCommand;
433    use crate::threading::threading_functions::block_on_task;
434    use crate::threading::threading_manager::*;
435
436    #[test]
437    fn test_queue_data() {
438        let expected = vec![
439            RUMString::from("Hello"),
440            RUMString::from("World!"),
441            RUMString::from("Overcast"),
442            RUMString::from("and"),
443            RUMString::from("Sad"),
444        ];
445        type TestResult = RUMResult<Vec<RUMString>>;
446        let mut queue: TaskManager<TestResult> = TaskManager::new(&5).unwrap();
447        let locked_args = RwLock::new(expected.clone());
448        let task_args = SafeTaskArgs::<RUMString>::new(locked_args);
449        let processor = rumtk_create_task!(
450            async |args: &SafeTaskArgs<RUMString>| -> TestResult {
451                let owned_args = Arc::clone(args);
452                let lock_future = owned_args.read();
453                let locked_args = lock_future.await;
454                let mut results = TaskItems::<RUMString>::with_capacity(locked_args.len());
455                print!("Contents: ");
456                for arg in locked_args.iter() {
457                    print!("{} ", &arg);
458                    results.push(RUMString::new(arg));
459                }
460                Ok(results)
461            },
462            task_args
463        );
464
465        queue.add_task::<_>(processor);
466        let results = queue.wait();
467
468        let mut result_data = Vec::<RUMString>::with_capacity(5);
469        for r in results {
470            for v in r.unwrap().result.clone().unwrap().iter() {
471                for value in v.iter() {
472                    result_data.push(value.clone());
473                }
474            }
475        }
476        assert_eq!(result_data, expected, "Results do not match expected!");
477    }
478
479    ///////////////////////////////////Net Tests/////////////////////////////////////////////////
480    #[test]
481    fn test_server_start() {
482        let server = match rumtk_create_server!("localhost", 0) {
483            Ok(server) => server,
484            Err(e) => panic!("Failed to create server because {}", e),
485        };
486    }
487
488    #[test]
489    fn test_server_send() {
490        let msg = RUMString::from("Hello World!");
491        let mut server = match rumtk_create_server!(LOCALHOST, 0) {
492            Ok(server) => server,
493            Err(e) => panic!("Failed to create server because {}", e),
494        };
495        let address_info = server.get_address_info().unwrap();
496        let (ip, port) = rumtk_get_ip_port!(address_info);
497        let mut client = match rumtk_connect!(port) {
498            Ok(client) => client,
499            Err(e) => panic!("Failed to create server because {}", e),
500        };
501        let client_id = client.get_address().unwrap();
502        match server.send(&client_id, &msg.to_raw()) {
503            Ok(_) => (),
504            Err(e) => panic!("Server failed to send message because {}", e),
505        };
506        let received_message = client.receive().unwrap();
507        assert_eq!(
508            &msg.len(),
509            &received_message.len(),
510            "Received message does not match expected length!"
511        );
512        assert_eq!(
513            &msg.to_raw(),
514            &received_message,
515            "{}",
516            rumtk_format!(
517                "Received message does not match sent message by server {:?}",
518                &received_message
519            )
520        );
521    }
522
523    #[test]
524    fn test_server_receive() {
525        let msg = RUMString::from("Hello World!");
526        let mut server = match rumtk_create_server!(LOCALHOST, 0) {
527            Ok(server) => server,
528            Err(e) => panic!("Failed to create server because {}", e),
529        };
530        let address_info = server.get_address_info().unwrap();
531        let (ip, port) = rumtk_get_ip_port!(address_info);
532        println!("Sleeping");
533        rumtk_sleep!(1);
534        let mut client = match rumtk_connect!(port) {
535            Ok(client) => client,
536            Err(e) => panic!("Failed to create server because {}", e),
537        };
538        println!("Sleeping");
539        rumtk_sleep!(1);
540        match client.send(msg.to_raw()) {
541            Ok(_) => (),
542            Err(e) => panic!("Failed to send message because {}", e),
543        };
544        let client_id = client.get_address().expect("Failed to get client id");
545        let incoming_message = server.receive(&client_id, true).unwrap().to_rumstring();
546        println!("Received message => {:?}", &incoming_message);
547        assert_eq!(&incoming_message, msg, "Received message corruption!");
548    }
549
550    #[test]
551    fn test_server_get_clients() {
552        let mut server = match rumtk_create_server!(LOCALHOST, 0) {
553            Ok(server) => server,
554            Err(e) => panic!("Failed to create server because {}", e),
555        };
556        let address_info = server.get_address_info().unwrap();
557        let (ip, port) = rumtk_get_ip_port!(address_info);
558        println!("Sleeping");
559        rumtk_sleep!(1);
560        let mut client = match rumtk_connect!(port) {
561            Ok(client) => client,
562            Err(e) => panic!("Failed to create client because {}", e),
563        };
564        println!("Sleeping");
565        rumtk_sleep!(1);
566        let expected_client_id = client.get_address().expect("Failed to get client id");
567        let clients = server.get_client_ids();
568        let incoming_client_id = clients.get(0).expect("Expected client to have connected!");
569        println!("Connected client id => {}", &incoming_client_id);
570        assert_eq!(
571            &incoming_client_id, &expected_client_id,
572            "Connected client does not match the connecting client! Client id => {}",
573            &incoming_client_id
574        );
575    }
576
577    #[test]
578    fn test_server_stop() {
579        let msg = RUMString::from("Hello World!");
580        let server = match rumtk_create_server!("localhost", 0) {
581            Ok(server) => server,
582            Err(e) => panic!("Failed to create server because {}", e),
583        };
584        println!("Sleeping");
585    }
586
587    #[test]
588    fn test_server_get_address_info() {
589        let msg = RUMString::from("Hello World!");
590        let mut server = match rumtk_create_server!("localhost", 0) {
591            Ok(server) => server,
592            Err(e) => panic!("Failed to create server because {}", e),
593        };
594        let addr = server.get_address_info().unwrap();
595        assert!(!addr.is_empty(), "No address returned....Got => {}", addr)
596    }
597
598    #[test]
599    fn test_client_send() {
600        let msg = RUMString::from("Hello World!");
601        let mut server = match rumtk_create_server!(LOCALHOST, 0) {
602            Ok(server) => server,
603            Err(e) => panic!("Failed to create server because {}", e),
604        };
605        let address_info = server.get_address_info().unwrap();
606        let (ip, port) = rumtk_get_ip_port!(address_info);
607        println!("Sleeping");
608        let mut client = match rumtk_connect!(port) {
609            Ok(client) => client,
610            Err(e) => panic!("Failed to create server because {}", e),
611        };
612        match client.send(msg.to_raw()) {
613            Ok(_) => (),
614            Err(e) => panic!("Failed to send message because {}", e),
615        };
616        let clients = server.get_client_ids();
617        let incoming_client_id = clients.first().expect("Expected client to have connected!");
618        let mut received_message = server.receive(incoming_client_id, true).unwrap();
619        if received_message.is_empty() {
620            received_message = server.receive(incoming_client_id, true).unwrap();
621        }
622        assert_eq!(
623            &msg.to_raw(),
624            &received_message,
625            "{}",
626            rumtk_format!(
627                "Received message does not match sent message by client {:?}",
628                &received_message
629            )
630        );
631    }
632
633    ////////////////////////////JSON Tests/////////////////////////////////
634
635    #[test]
636    fn test_serialize_json() {
637        #[derive(RUMSerialize)]
638        struct MyStruct {
639            hello: RUMString,
640        }
641
642        let hw = MyStruct {
643            hello: RUMString::from("World"),
644        };
645        let hw_str = rumtk_serialize!(&hw, true).unwrap();
646
647        assert!(
648            !hw_str.is_empty(),
649            "Empty JSON string generated from the test struct!"
650        );
651    }
652
653    #[test]
654    fn test_deserialize_serde_json() {
655        use serde_json::{from_str, to_string};
656
657        #[derive(RUMSerialize, RUMDeserialize, PartialEq, Debug, Clone)]
658        struct MyStruct {
659            hello: RUMString,
660        }
661
662        let hw = MyStruct {
663            hello: RUMString::from("World"),
664        };
665        let hw_str = to_string(&hw).unwrap();
666        let new_hw: MyStruct = from_str(&hw_str).unwrap();
667
668        assert_eq!(
669            new_hw, hw,
670            "Deserialized JSON does not match the expected value!"
671        );
672    }
673
674    #[test]
675    fn test_deserialize_json() {
676        #[derive(RUMSerialize, RUMDeserialize, PartialEq)]
677        struct MyStruct {
678            hello: RUMString,
679        }
680
681        let hw = MyStruct {
682            hello: RUMString::from("World"),
683        };
684        let hw_str = rumtk_serialize!(&hw, true).unwrap();
685        let new_hw: MyStruct = rumtk_deserialize!(&hw_str).unwrap();
686
687        assert!(
688            new_hw == hw,
689            "Deserialized JSON does not match the expected value!"
690        );
691    }
692
693    /*
694    #[test]
695    fn test_escape_unescape_json() {
696        #[derive(Serialize, Deserialize, PartialEq)]
697        struct MyStruct {
698            hello: RUMString,
699        }
700
701        let hw = MyStruct {
702            hello: RUMString::from("World"),
703        };
704
705        let hw_str = rumtk_serialize!(&hw, true).unwrap();
706        let hw_escaped_str = strings::basic_escape(&hw_str);
707        println!("Escaped => {}", hw_escaped_str);
708
709        let hw_unescaped_str = strings::unescape_string(&hw_escaped_str).unwrap();
710        println!("Unescaped => {}", hw_unescaped_str);
711        assert_eq!(
712            hw_str.to_rumstring(),
713            hw_unescaped_str.to_rumstring(),
714            "Unescaped serialized JSON mismatch!"
715        );
716
717        let new_hw: MyStruct = rumtk_deserialize!(&hw_unescaped_str).unwrap();
718
719        assert!(
720            new_hw == hw,
721            "Deserialized JSON does not match the expected value!"
722        );
723    }
724    */
725
726    ////////////////////////////CLI Tests/////////////////////////////////
727
728    #[test]
729    fn test_print_license_notice() {
730        print_license_notice("RUMTK", "2025", &vec!["Luis M. Santos, M.D."]);
731    }
732
733    //////////////////////////////////////////////////////////////////////////////////////////////
734
735    ////////////////////////////Pipeline Tests/////////////////////////////////
736
737    #[test]
738    fn test_pipe_processes() {
739        let ls_name = "ls";
740        let mut ls_command = RUMCommand::default();
741        ls_command.path = RUMString::from(ls_name);
742        let mut sys_ls_command = pipeline_generate_command(&ls_command);
743        sys_ls_command.stdin(Stdio::piped());
744        sys_ls_command.stdout(Stdio::piped());
745
746        let wc_name = "wc";
747        let mut wc_command = RUMCommand::default();
748        wc_command.path = RUMString::from(wc_name);
749        let mut sys_wc_command = pipeline_generate_command(&wc_command);
750
751        let mut sys_ls_process = pipeline_spawn_process(&mut sys_ls_command).unwrap();
752        pipeline_pipe_processes(&mut sys_ls_process, &mut sys_wc_command).unwrap();
753        let mut sys_wc_process = pipeline_spawn_process(&mut sys_wc_command).unwrap();
754
755        sys_ls_process.wait();
756        sys_wc_process.wait();
757    }
758
759    //////////////////////////////////////////////////////////////////////////////////////////////
760}