1 /** 2 * Copyright: Copyright Jason White, 2014-2016 3 * License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 * Authors: Jason White 5 */ 6 module io.stream.traits; 7 8 import io.stream.types : From; 9 10 /** 11 * Checks if a type is a source. A source is a stream that can be read from and 12 * must define the member function $(D read). The stream can be either a class 13 * or a struct. 14 */ 15 enum isSource(Stream) = 16 is(typeof({ 17 Stream s = void; 18 ubyte[] buf; 19 ulong n = s.read(buf); 20 })); 21 22 unittest 23 { 24 static struct A {} 25 static assert(!isSource!A); 26 27 static struct B 28 { 29 size_t read(ubyte[] buf) { return buf.length; } 30 } 31 32 static assert(isSource!B); 33 34 static struct C 35 { 36 void read() {} 37 } 38 39 static assert(!isSource!C); 40 } 41 42 /** 43 * Checks if a type is a sink. A sink is a stream that can be written to and must 44 * define the member function $(D write). The stream can be either a class or a 45 * struct. 46 */ 47 enum isSink(Stream) = 48 is(typeof({ 49 Stream s = void; 50 immutable ubyte[] data; 51 ulong n = s.write(data); 52 })); 53 54 unittest 55 { 56 static struct A {} 57 static assert(!isSink!A); 58 59 static struct B 60 { 61 size_t write(in ubyte[] data) { return 0; } 62 } 63 64 static assert(isSink!B); 65 66 static struct C 67 { 68 void write() {} 69 } 70 71 static assert(!isSink!C); 72 } 73 74 /** 75 * Checks if a type is seekable. A seekable stream must define the member 76 * function $(D seek). The stream can be either a class or a struct. 77 */ 78 enum isSeekable(Stream) = 79 is(typeof({ 80 Stream s = void; 81 auto pos = s.seekTo(0, From.start); 82 })); 83 84 unittest 85 { 86 static struct A {} 87 static assert(!isSeekable!A); 88 89 static struct B { 90 long seekTo(long offset, From from) { return 0; } 91 } 92 static assert(isSeekable!B); 93 94 static struct C { 95 // Should return the current position. 96 void seekTo(long offset, From from) {} 97 } 98 static assert(!isSeekable!C); 99 } 100 101 /** 102 * Checks if the type is both a source and a sink. 103 */ 104 enum isSourceSink(Stream) = isSource!Stream && isSink!Stream; 105 106 unittest 107 { 108 static struct A 109 { 110 size_t write(in ubyte[] data) { return 0; } 111 } 112 113 static assert(!isSourceSink!A); 114 115 static struct B 116 { 117 size_t write(in ubyte[] data) { return 0; } 118 size_t read(ubyte[] buf) { return buf.length; } 119 } 120 121 static assert(isSourceSink!B); 122 } 123 124 /** 125 * Checks if the type is either a source or a sink (i.e., a stream). 126 */ 127 enum isStream(Stream) = isSource!Stream || isSink!Stream; 128 129 unittest 130 { 131 static struct A 132 { 133 size_t write(in ubyte[] data) { return 0; } 134 } 135 136 static assert(isStream!A); 137 138 static struct B 139 { 140 size_t read(ubyte[] buf) { return buf.length; } 141 } 142 143 static assert(isStream!B); 144 145 static struct C 146 { 147 long seekTo(long offset, From from) { return 0; } 148 } 149 150 static assert(!isStream!C); 151 }