001    /*
002     * Copyright (C) 2011 The Guava Authors
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005     * in compliance with the License. You may obtain a copy of the License at
006     *
007     * http://www.apache.org/licenses/LICENSE-2.0
008     *
009     * Unless required by applicable law or agreed to in writing, software distributed under the License
010     * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011     * or implied. See the License for the specific language governing permissions and limitations under
012     * the License.
013     */
014    
015    package com.google.common.hash;
016    
017    import com.google.common.annotations.Beta;
018    import com.google.common.base.Preconditions;
019    
020    import java.io.OutputStream;
021    
022    /**
023     * Funnels for common types. All implementations are serializable.
024     *
025     * @author Dimitris Andreou
026     * @since 11.0
027     */
028    @Beta
029    public final class Funnels {
030      private Funnels() {}
031    
032      /**
033       * Returns a funnel that extracts the bytes from a {@code byte} array.
034       */
035      public static Funnel<byte[]> byteArrayFunnel() {
036        return ByteArrayFunnel.INSTANCE;
037      }
038    
039      private enum ByteArrayFunnel implements Funnel<byte[]> {
040        INSTANCE;
041    
042        public void funnel(byte[] from, PrimitiveSink into) {
043          into.putBytes(from);
044        }
045    
046        @Override public String toString() {
047          return "Funnels.byteArrayFunnel()";
048        }
049      }
050    
051      /**
052       * Returns a funnel that extracts the characters from a {@code CharSequence}.
053       */
054      public static Funnel<CharSequence> stringFunnel() {
055        return StringFunnel.INSTANCE;
056      }
057    
058      private enum StringFunnel implements Funnel<CharSequence> {
059        INSTANCE;
060    
061        public void funnel(CharSequence from, PrimitiveSink into) {
062          into.putString(from);
063        }
064    
065        @Override public String toString() {
066          return "Funnels.stringFunnel()";
067        }
068      }
069      
070      /**
071       * Returns a funnel for integers.
072       * 
073       * @since 13.0
074       */
075      public static Funnel<Integer> integerFunnel() {
076        return IntegerFunnel.INSTANCE;
077      }
078      
079      private enum IntegerFunnel implements Funnel<Integer> {
080        INSTANCE;
081        
082        public void funnel(Integer from, PrimitiveSink into) {
083          into.putInt(from);
084        }
085        
086        @Override public String toString() {
087          return "Funnels.integerFunnel()";
088        }
089      }
090    
091      /**
092       * Returns a funnel for longs.
093       * 
094       * @since 13.0
095       */
096      public static Funnel<Long> longFunnel() {
097        return LongFunnel.INSTANCE;
098      }
099      
100      private enum LongFunnel implements Funnel<Long> {
101        INSTANCE;
102        
103        public void funnel(Long from, PrimitiveSink into) {
104          into.putLong(from);
105        }
106        
107        @Override public String toString() {
108          return "Funnels.longFunnel()";
109        }
110      }
111      
112      /**
113       * Wraps a {@code PrimitiveSink} as an {@link OutputStream}, so it is easy to
114       * {@link Funnel#funnel funnel} an object to a {@code PrimitiveSink}
115       * if there is already a way to write the contents of the object to an {@code OutputStream}.  
116       * 
117       * <p>The {@code close} and {@code flush} methods of the returned {@code OutputStream}
118       * do nothing, and no method throws {@code IOException}.
119       * 
120       * @since 13.0
121       */
122      public static OutputStream asOutputStream(PrimitiveSink sink) {
123        return new SinkAsStream(sink);
124      }
125      
126      private static class SinkAsStream extends OutputStream {
127        final PrimitiveSink sink;
128        SinkAsStream(PrimitiveSink sink) {
129          this.sink = Preconditions.checkNotNull(sink);
130        }
131        
132        @Override public void write(int b) {
133          sink.putByte((byte) b);
134        }
135    
136        @Override public void write(byte[] bytes) {
137          sink.putBytes(bytes);
138        }
139    
140        @Override public void write(byte[] bytes, int off, int len) {
141          sink.putBytes(bytes, off, len);
142        }
143        
144        @Override public String toString() {
145          return "Funnels.asOutputStream(" + sink + ")";
146        }
147      }
148    }