GwtWorkarounds.java revision 7dd252788645e940eada959bdde927426e2531c9
1/* 2 * Copyright (C) 2012 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 15package com.google.common.io; 16 17import static com.google.common.base.Preconditions.checkNotNull; 18import static com.google.common.base.Preconditions.checkPositionIndexes; 19 20import com.google.common.annotations.GwtCompatible; 21import com.google.common.annotations.GwtIncompatible; 22 23import java.io.IOException; 24import java.io.InputStream; 25import java.io.OutputStream; 26import java.io.Reader; 27import java.io.Writer; 28 29/** 30 * Provides simple GWT-compatible substitutes for {@code InputStream}, {@code OutputStream}, 31 * {@code Reader}, and {@code Writer} so that {@code BaseEncoding} can use streaming implementations 32 * while remaining GWT-compatible. 33 * 34 * @author Louis Wasserman 35 */ 36@GwtCompatible(emulated = true) 37final class GwtWorkarounds { 38 private GwtWorkarounds() {} 39 40 /** 41 * A GWT-compatible substitute for a {@code Reader}. 42 */ 43 interface CharInput { 44 int read() throws IOException; 45 46 void close() throws IOException; 47 } 48 49 /** 50 * Views a {@code Reader} as a {@code CharInput}. 51 */ 52 @GwtIncompatible("Reader") 53 static CharInput asCharInput(final Reader reader) { 54 checkNotNull(reader); 55 return new CharInput() { 56 57 public int read() throws IOException { 58 return reader.read(); 59 } 60 61 public void close() throws IOException { 62 reader.close(); 63 } 64 }; 65 } 66 67 /** 68 * Views a {@code CharSequence} as a {@code CharInput}. 69 */ 70 static CharInput asCharInput(final CharSequence chars) { 71 checkNotNull(chars); 72 return new CharInput() { 73 int index = 0; 74 75 public int read() { 76 if (index < chars.length()) { 77 return chars.charAt(index++); 78 } else { 79 return -1; 80 } 81 } 82 83 public void close() { 84 index = chars.length(); 85 } 86 }; 87 } 88 89 /** 90 * A GWT-compatible substitute for an {@code InputStream}. 91 */ 92 interface ByteInput { 93 int read() throws IOException; 94 95 void close() throws IOException; 96 } 97 98 /** 99 * Views a {@code ByteInput} as an {@code InputStream}. 100 */ 101 @GwtIncompatible("InputStream") 102 static InputStream asInputStream(final ByteInput input) { 103 checkNotNull(input); 104 return new InputStream() { 105 106 @Override 107 public int read() throws IOException { 108 return input.read(); 109 } 110 111 @Override 112 public int read(byte[] b, int off, int len) throws IOException { 113 checkNotNull(b); 114 checkPositionIndexes(off, off + len, b.length); 115 if (len == 0) { 116 return 0; 117 } 118 int firstByte = read(); 119 if (firstByte == -1) { 120 return -1; 121 } 122 b[off] = (byte) firstByte; 123 for (int dst = 1; dst < len; dst++) { 124 int readByte = read(); 125 if (readByte == -1) { 126 return dst; 127 } 128 b[off + dst] = (byte) readByte; 129 } 130 return len; 131 } 132 133 @Override 134 public void close() throws IOException { 135 input.close(); 136 } 137 }; 138 } 139 140 /** 141 * A GWT-compatible substitute for an {@code OutputStream}. 142 */ 143 interface ByteOutput { 144 void write(byte b) throws IOException; 145 146 void flush() throws IOException; 147 148 void close() throws IOException; 149 } 150 151 /** 152 * Views a {@code ByteOutput} as an {@code OutputStream}. 153 */ 154 @GwtIncompatible("OutputStream") 155 static OutputStream asOutputStream(final ByteOutput output) { 156 checkNotNull(output); 157 return new OutputStream() { 158 159 @Override 160 public void write(int b) throws IOException { 161 output.write((byte) b); 162 } 163 164 @Override 165 public void flush() throws IOException { 166 output.flush(); 167 } 168 169 @Override 170 public void close() throws IOException { 171 output.close(); 172 } 173 }; 174 } 175 176 /** 177 * A GWT-compatible substitute for a {@code Writer}. 178 */ 179 interface CharOutput { 180 void write(char c) throws IOException; 181 182 void flush() throws IOException; 183 184 void close() throws IOException; 185 } 186 187 /** 188 * Views a {@code Writer} as a {@code CharOutput}. 189 */ 190 @GwtIncompatible("Writer") 191 static CharOutput asCharOutput(final Writer writer) { 192 checkNotNull(writer); 193 return new CharOutput() { 194 195 public void write(char c) throws IOException { 196 writer.append(c); 197 } 198 199 public void flush() throws IOException { 200 writer.flush(); 201 } 202 203 public void close() throws IOException { 204 writer.close(); 205 } 206 }; 207 } 208 209 /** 210 * Returns a {@code CharOutput} whose {@code toString()} method can be used 211 * to get the combined output. 212 */ 213 static CharOutput stringBuilderOutput(int initialSize) { 214 final StringBuilder builder = new StringBuilder(initialSize); 215 return new CharOutput() { 216 217 public void write(char c) { 218 builder.append(c); 219 } 220 221 public void flush() {} 222 223 public void close() {} 224 225 @Override 226 public String toString() { 227 return builder.toString(); 228 } 229 }; 230 } 231} 232