1 /** File I/O pipes. 2 * 3 * Authors: $(LINK2 https://github.com/epi, Adrian Matoga) 4 * Copyright: © 2016 Adrian Matoga 5 * License: $(LINK2 http://www.boost.org/users/license.html, BSL-1.0). 6 */ 7 module flod.file; 8 9 import std.stdio : File; 10 11 import flod.traits : source, sink, Method; 12 import flod.pipeline : isSchema; 13 14 @source!ubyte(Method.pull) 15 private struct FileReader(alias Context, A...) { 16 mixin Context!A; 17 private: 18 File file; 19 20 public: 21 this(in char[] name) { file = File(name, "rb"); } 22 23 size_t pull()(ubyte[] buf) 24 { 25 return file.rawRead(buf).length; 26 } 27 } 28 29 /// Returns a pipe that reads `ubyte`s from file `name`. 30 auto read(in char[] name) 31 { 32 import flod.pipeline : pipe; 33 return pipe!FileReader(name); 34 } 35 36 @sink(Method.push) 37 private struct FileWriter(alias Context, A...) { 38 mixin Context!A; 39 private: 40 File file; 41 42 public: 43 this(File file) { this.file = file; } 44 this(in char[] name) { file = File(name, "wb"); } 45 46 size_t push(const(InputElementType)[] buf) 47 { 48 file.rawWrite(buf); 49 return buf.length; 50 } 51 } 52 53 /// Returns a pipe that writes to file `name`. 54 auto write(S)(S schema, in char[] name) 55 if (isSchema!S) 56 { 57 import flod.pipeline : pipe; 58 return schema.pipe!FileWriter(name); 59 } 60 61 /// Returns a pipe that writes to file `file`. 62 auto write(S)(S schema, File file) 63 if (isSchema!S) 64 { 65 import flod.pipeline : pipe; 66 return schema.pipe!FileWriter(file); 67 } 68 69 unittest { 70 import std.file : remove, exists, stdread = read; 71 scope(exit) { 72 if (exists(".test")) 73 remove(".test"); 74 } 75 auto f1 = stdread("/etc/passwd"); 76 77 read("/etc/passwd").write(".test"); 78 auto f2 = stdread(".test"); 79 assert(f1 == f2); 80 81 read("/etc/passwd").write(File(".test", "wb")); 82 auto f3 = stdread(".test"); 83 assert(f1 == f3); 84 }