// =================================================================================================
// Copyright 2011 Twitter, Inc.
// -------------------------------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this work except in compliance with the License.
// You may obtain a copy of the License in the LICENSE file, or at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =================================================================================================
package com.twitter.common.memcached;
import com.google.common.base.Function;
import com.twitter.common.io.Codec;
import com.twitter.common.io.ThriftCodec;
import net.spy.memcached.CachedData;
import net.spy.memcached.transcoders.Transcoder;
import org.apache.thrift.TBase;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TTransport;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
* A memcached value transcoder that can transcode for a given thrift type.
*
* @param <T> the type to transcode
*
* @author John Sirois
*/
public class ThriftTranscoder<T extends TBase> implements Transcoder<T> {
/**
* A convenience method that creates a new Transcoder for the given thrift type using the thrift
* compact binary encoding.
*
* @param thriftStructType the type to transcode
* @param <T> the type to transcode
* @return a new Transcoder that can transcode the given thrift type
*/
public static <T extends TBase> Transcoder<T> of(Class<T> thriftStructType) {
return new ThriftTranscoder<T>(thriftStructType, ThriftCodec.COMPACT_PROTOCOL);
}
private final Codec<T> codec;
/**
* @param thriftStructType the type to transcode
* @param encoder a factory that can produce a transport for a given protocol
*/
public ThriftTranscoder(Class<T> thriftStructType, Function<TTransport, TProtocol> encoder) {
this.codec = new ThriftCodec<T>(thriftStructType, encoder);
}
@Override
public CachedData encode(T thriftStruct) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
if (thriftStruct != null) {
try {
codec.serialize(thriftStruct, buffer);
} catch (IOException e) {
throw new RuntimeException("Unable to encode value: " + thriftStruct, e);
}
}
return new CachedData(0, buffer.toByteArray(), CachedData.MAX_SIZE);
}
@Override
public T decode(CachedData cachedData) {
byte[] data = cachedData.getData();
if (data == null || data.length == 0) {
return null;
}
try {
return codec.deserialize(new ByteArrayInputStream(data));
} catch (IOException e) {
throw new RuntimeException("Unable to decode data: " + data, e);
}
}
@Override
public boolean asyncDecode(CachedData cachedData) {
return false;
}
@Override
public int getMaxSize() {
return CachedData.MAX_SIZE;
}
}