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        
047        @Override
048        public String toString() {
049          return "Funnels.byteArrayFunnel()";
050        }
051      }
052    
053      /**
054       * Returns a funnel that extracts the characters from a {@code CharSequence}.
055       */
056      public static Funnel<CharSequence> stringFunnel() {
057        return StringFunnel.INSTANCE;
058      }
059    
060      private enum StringFunnel implements Funnel<CharSequence> {
061        INSTANCE;
062    
063        public void funnel(CharSequence from, PrimitiveSink into) {
064          into.putString(from);
065        }
066    
067        
068        @Override
069        public String toString() {
070          return "Funnels.stringFunnel()";
071        }
072      }
073      
074      /**
075       * Returns a funnel for integers.
076       * 
077       * @since 13.0
078       */
079      public static Funnel<Integer> integerFunnel() {
080        return IntegerFunnel.INSTANCE;
081      }
082      
083      private enum IntegerFunnel implements Funnel<Integer> {
084        INSTANCE;
085        
086        public void funnel(Integer from, PrimitiveSink into) {
087          into.putInt(from);
088        }
089        
090        @Override
091        public String toString() {
092          return "Funnels.integerFunnel()";
093        }
094      }
095    
096      /**
097       * Returns a funnel for longs.
098       * 
099       * @since 13.0
100       */
101      public static Funnel<Long> longFunnel() {
102        return LongFunnel.INSTANCE;
103      }
104      
105      private enum LongFunnel implements Funnel<Long> {
106        INSTANCE;
107        
108        public void funnel(Long from, PrimitiveSink into) {
109          into.putLong(from);
110        }
111        
112        @Override
113        public String toString() {
114          return "Funnels.longFunnel()";
115        }
116      }
117      
118      /**
119       * Wraps a {@code PrimitiveSink} as an {@link OutputStream}, so it is easy to
120       * {@link Funnel#funnel funnel} an object to a {@code PrimitiveSink}
121       * if there is already a way to write the contents of the object to an {@code OutputStream}.  
122       * 
123       * <p>The {@code close} and {@code flush} methods of the returned {@code OutputStream}
124       * do nothing, and no method throws {@code IOException}.
125       * 
126       * @since 13.0
127       */
128      public static OutputStream asOutputStream(PrimitiveSink sink) {
129        return new SinkAsStream(sink);
130      }
131      
132      private static class SinkAsStream extends OutputStream {
133        final PrimitiveSink sink;
134        SinkAsStream(PrimitiveSink sink) {
135          this.sink = Preconditions.checkNotNull(sink);
136        }
137        
138        @Override
139        public void write(int b) {
140          sink.putByte((byte) b);
141        }
142    
143        @Override
144        public void write(byte[] bytes) {
145          sink.putBytes(bytes);
146        }
147    
148        @Override
149        public void write(byte[] bytes, int off, int len) {
150          sink.putBytes(bytes, off, len);
151        }
152        
153        @Override
154        public String toString() {
155          return "Funnels.asOutputStream(" + sink + ")";
156        }
157      }
158    }