1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
//! Defines "provider" traits and implementations for different types of I/O operations. //! //! The purpose of this is mainly for dependency injection: by having your code depend on a //! generic provider, it can be tested by giving it a virtual, inspectable implementation of that //! provider. In production, the "real" implementation can be used. //! //! Each type of provider exists in its own submodule and can be used independently. However, //! this module also contains the all-encompassing `IoProvider` trait which provides access to //! all of them. If you have a lot of I/O dependencies, it might be easier to create and pass //! around one `&mut IoProvider` rather than several different providers. //! //! # Examples //! //! ``` //! extern crate io_providers; //! //! use std::io::Write; //! use std::path::Path; //! use io_providers::{IoProvider, LocalIoProvider, VirtualIoProvider}; //! use io_providers::env::Provider as EnvProvider; //! use io_providers::stream::Provider as StreamProvider; //! //! /// Gets the current working directory and prints it to stdout. //! fn do_work(io: &mut IoProvider) { //! let cur_dir = io.env().current_dir().unwrap(); //! let stdout = io.stream().output(); //! writeln!(stdout, "The current directory is: {}", cur_dir.to_str().unwrap()).unwrap(); //! } //! //! fn main() { //! test_do_work_prints_current_dir(); //! //! // Use a local I/O provider here to get real interaction with the system //! let mut io = LocalIoProvider::new(); //! do_work(&mut io); //! } //! //! fn test_do_work_prints_current_dir() { //! // Use a virtual I/O provider here so we can verify how it was used //! let mut virtual_io = VirtualIoProvider::new(); //! virtual_io.env().set_current_dir(Path::new("/foo/bar")).unwrap(); //! //! do_work(&mut virtual_io); //! //! assert_eq!( //! "The current directory is: /foo/bar\n", //! ::std::str::from_utf8(virtual_io.virtual_stream().read_output()).unwrap()); //! } //! ``` pub mod env; pub mod stream; /// Provides access to an environment provider and a stream provider. /// /// See `env::Provider` and `stream::Provider` for more information. pub trait IoProvider { /// Gets the `env::Provider`. fn env<'a>(&'a mut self) -> &'a mut env::Provider; /// Gets the `stream::Provider`. fn stream<'a>(&'a mut self) -> &'a mut stream::Provider; } /// "Real" implementer of `IoProvider`, using standard streams and the local environment. /// /// See `env::Local` and `stream::Std` for more information. pub struct LocalIoProvider { env_provider: env::Local, stream_provider: stream::Std, } impl LocalIoProvider { /// Creates a new `LocalIoProvider`. pub fn new() -> LocalIoProvider { LocalIoProvider { env_provider: env::Local, stream_provider: stream::Std::new(), } } } impl IoProvider for LocalIoProvider { fn env<'a>(&'a mut self) -> &'a mut env::Provider { &mut self.env_provider } fn stream<'a>(&'a mut self) -> &'a mut stream::Provider { &mut self.stream_provider } } /// Virtual implementer of `IoProvider`, using in-memory data which can be inspected. /// /// See `env::Virtual` and `stream::Virtual` for more information. pub struct VirtualIoProvider { env_provider: env::Virtual, stream_provider: stream::Virtual, } impl VirtualIoProvider { /// Creates a new `VirtualIoProvider`. pub fn new() -> VirtualIoProvider { VirtualIoProvider { env_provider: env::Virtual::new(), stream_provider: stream::Virtual::new(), } } /// Gets the `env::Virtual` provider. pub fn virtual_env<'a>(&'a mut self) -> &'a mut env::Virtual { &mut self.env_provider } /// Gets the `stream::Virtual` provider. pub fn virtual_stream<'a>(&'a mut self) -> &'a mut stream::Virtual { &mut self.stream_provider } } impl IoProvider for VirtualIoProvider { fn env<'a>(&'a mut self) -> &'a mut env::Provider { &mut self.env_provider } fn stream<'a>(&'a mut self) -> &'a mut stream::Provider { &mut self.stream_provider } }