• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 
15 package com.google.common.hash;
16 
17 import com.google.common.annotations.Beta;
18 import com.google.common.base.Preconditions;
19 
20 import java.io.OutputStream;
21 import java.io.Serializable;
22 import java.nio.charset.Charset;
23 
24 import javax.annotation.Nullable;
25 
26 /**
27  * Funnels for common types. All implementations are serializable.
28  *
29  * @author Dimitris Andreou
30  * @since 11.0
31  */
32 @Beta
33 public final class Funnels {
Funnels()34   private Funnels() {}
35 
36   /**
37    * Returns a funnel that extracts the bytes from a {@code byte} array.
38    */
byteArrayFunnel()39   public static Funnel<byte[]> byteArrayFunnel() {
40     return ByteArrayFunnel.INSTANCE;
41   }
42 
43   private enum ByteArrayFunnel implements Funnel<byte[]> {
44     INSTANCE;
45 
funnel(byte[] from, PrimitiveSink into)46     public void funnel(byte[] from, PrimitiveSink into) {
47       into.putBytes(from);
48     }
49 
toString()50     @Override public String toString() {
51       return "Funnels.byteArrayFunnel()";
52     }
53   }
54 
55   /**
56    * Returns a funnel that extracts the characters from a {@code CharSequence}, a character at a
57    * time, without performing any encoding. If you need to use a specific encoding, use
58    * {@link Funnels#stringFunnel(Charset)} instead.
59    *
60    * @since 15.0 (since 11.0 as {@code Funnels.stringFunnel()}.
61    */
unencodedCharsFunnel()62   public static Funnel<CharSequence> unencodedCharsFunnel() {
63     return UnencodedCharsFunnel.INSTANCE;
64   }
65 
66   private enum UnencodedCharsFunnel implements Funnel<CharSequence> {
67     INSTANCE;
68 
funnel(CharSequence from, PrimitiveSink into)69     public void funnel(CharSequence from, PrimitiveSink into) {
70       into.putUnencodedChars(from);
71     }
72 
toString()73     @Override public String toString() {
74       return "Funnels.unencodedCharsFunnel()";
75     }
76   }
77 
78   /**
79    * Returns a funnel that encodes the characters of a {@code CharSequence} with the specified
80    * {@code Charset}.
81    *
82    * @since 15.0
83    */
stringFunnel(Charset charset)84   public static Funnel<CharSequence> stringFunnel(Charset charset) {
85     return new StringCharsetFunnel(charset);
86   }
87 
88   private static class StringCharsetFunnel implements Funnel<CharSequence>, Serializable {
89     private final Charset charset;
90 
StringCharsetFunnel(Charset charset)91     StringCharsetFunnel(Charset charset) {
92       this.charset = Preconditions.checkNotNull(charset);
93     }
94 
funnel(CharSequence from, PrimitiveSink into)95     public void funnel(CharSequence from, PrimitiveSink into) {
96       into.putString(from, charset);
97     }
98 
toString()99     @Override public String toString() {
100       return "Funnels.stringFunnel(" + charset.name() + ")";
101     }
102 
equals(@ullable Object o)103     @Override public boolean equals(@Nullable Object o) {
104       if (o instanceof StringCharsetFunnel) {
105         StringCharsetFunnel funnel = (StringCharsetFunnel) o;
106         return this.charset.equals(funnel.charset);
107       }
108       return false;
109     }
110 
hashCode()111     @Override public int hashCode() {
112       return StringCharsetFunnel.class.hashCode() ^ charset.hashCode();
113     }
114 
writeReplace()115     Object writeReplace() {
116       return new SerializedForm(charset);
117     }
118 
119     private static class SerializedForm implements Serializable {
120       private final String charsetCanonicalName;
121 
SerializedForm(Charset charset)122       SerializedForm(Charset charset) {
123         this.charsetCanonicalName = charset.name();
124       }
125 
readResolve()126       private Object readResolve() {
127         return stringFunnel(Charset.forName(charsetCanonicalName));
128       }
129 
130       private static final long serialVersionUID = 0;
131     }
132   }
133 
134   /**
135    * Returns a funnel for integers.
136    *
137    * @since 13.0
138    */
integerFunnel()139   public static Funnel<Integer> integerFunnel() {
140     return IntegerFunnel.INSTANCE;
141   }
142 
143   private enum IntegerFunnel implements Funnel<Integer> {
144     INSTANCE;
145 
funnel(Integer from, PrimitiveSink into)146     public void funnel(Integer from, PrimitiveSink into) {
147       into.putInt(from);
148     }
149 
toString()150     @Override public String toString() {
151       return "Funnels.integerFunnel()";
152     }
153   }
154 
155   /**
156    * Returns a funnel that processes an {@code Iterable} by funneling its elements in iteration
157    * order with the specified funnel.  No separators are added between the elements.
158    *
159    * @since 15.0
160    */
sequentialFunnel(Funnel<E> elementFunnel)161   public static <E> Funnel<Iterable<? extends E>> sequentialFunnel(Funnel<E> elementFunnel) {
162     return new SequentialFunnel<E>(elementFunnel);
163   }
164 
165   private static class SequentialFunnel<E> implements Funnel<Iterable<? extends E>>, Serializable {
166     private final Funnel<E> elementFunnel;
167 
SequentialFunnel(Funnel<E> elementFunnel)168     SequentialFunnel(Funnel<E> elementFunnel) {
169       this.elementFunnel = Preconditions.checkNotNull(elementFunnel);
170     }
171 
funnel(Iterable<? extends E> from, PrimitiveSink into)172     public void funnel(Iterable<? extends E> from, PrimitiveSink into) {
173       for (E e : from) {
174         elementFunnel.funnel(e, into);
175       }
176     }
177 
toString()178     @Override public String toString() {
179       return "Funnels.sequentialFunnel(" + elementFunnel + ")";
180     }
181 
equals(@ullable Object o)182     @Override public boolean equals(@Nullable Object o) {
183       if (o instanceof SequentialFunnel) {
184         SequentialFunnel<?> funnel = (SequentialFunnel<?>) o;
185         return elementFunnel.equals(funnel.elementFunnel);
186       }
187       return false;
188     }
189 
hashCode()190     @Override public int hashCode() {
191       return SequentialFunnel.class.hashCode() ^ elementFunnel.hashCode();
192     }
193   }
194 
195   /**
196    * Returns a funnel for longs.
197    *
198    * @since 13.0
199    */
longFunnel()200   public static Funnel<Long> longFunnel() {
201     return LongFunnel.INSTANCE;
202   }
203 
204   private enum LongFunnel implements Funnel<Long> {
205     INSTANCE;
206 
funnel(Long from, PrimitiveSink into)207     public void funnel(Long from, PrimitiveSink into) {
208       into.putLong(from);
209     }
210 
toString()211     @Override public String toString() {
212       return "Funnels.longFunnel()";
213     }
214   }
215 
216   /**
217    * Wraps a {@code PrimitiveSink} as an {@link OutputStream}, so it is easy to
218    * {@link Funnel#funnel funnel} an object to a {@code PrimitiveSink}
219    * if there is already a way to write the contents of the object to an {@code OutputStream}.
220    *
221    * <p>The {@code close} and {@code flush} methods of the returned {@code OutputStream}
222    * do nothing, and no method throws {@code IOException}.
223    *
224    * @since 13.0
225    */
asOutputStream(PrimitiveSink sink)226   public static OutputStream asOutputStream(PrimitiveSink sink) {
227     return new SinkAsStream(sink);
228   }
229 
230   private static class SinkAsStream extends OutputStream {
231     final PrimitiveSink sink;
SinkAsStream(PrimitiveSink sink)232     SinkAsStream(PrimitiveSink sink) {
233       this.sink = Preconditions.checkNotNull(sink);
234     }
235 
write(int b)236     @Override public void write(int b) {
237       sink.putByte((byte) b);
238     }
239 
write(byte[] bytes)240     @Override public void write(byte[] bytes) {
241       sink.putBytes(bytes);
242     }
243 
write(byte[] bytes, int off, int len)244     @Override public void write(byte[] bytes, int off, int len) {
245       sink.putBytes(bytes, off, len);
246     }
247 
toString()248     @Override public String toString() {
249       return "Funnels.asOutputStream(" + sink + ")";
250     }
251   }
252 }
253