001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.types;
019
020import com.google.protobuf.CodedInputStream;
021import com.google.protobuf.CodedOutputStream;
022import com.google.protobuf.Message;
023import org.apache.hadoop.hbase.util.Order;
024import org.apache.hadoop.hbase.util.PositionedByteRange;
025import org.apache.yetus.audience.InterfaceAudience;
026
027/**
028 * A base-class for {@link DataType} implementations backed by protobuf. See
029 * {@code PBKeyValue} in {@code hbase-examples} module.
030 */
031@InterfaceAudience.Public
032public abstract class PBType<T extends Message> implements DataType<T> {
033  @Override
034  public boolean isOrderPreserving() {
035    return false;
036  }
037
038  @Override
039  public Order getOrder() {
040    return null;
041  }
042
043  @Override
044  public boolean isNullable() {
045    return false;
046  }
047
048  @Override
049  public boolean isSkippable() {
050    return true;
051  }
052
053  @Override
054  public int encodedLength(T val) {
055    return val.getSerializedSize();
056  }
057
058  /**
059   * Create a {@link CodedInputStream} from a {@link PositionedByteRange}. Be sure to update
060   * {@code src}'s position after consuming from the stream.
061   * <p>For example:
062   * <pre>
063   * Foo.Builder builder = ...
064   * CodedInputStream is = inputStreamFromByteRange(src);
065   * Foo ret = builder.mergeFrom(is).build();
066   * src.setPosition(src.getPosition() + is.getTotalBytesRead());
067   * </pre>
068   */
069  public static CodedInputStream inputStreamFromByteRange(PositionedByteRange src) {
070    return CodedInputStream.newInstance(
071      src.getBytes(),
072      src.getOffset() + src.getPosition(),
073      src.getRemaining());
074  }
075
076  /**
077   * Create a {@link CodedOutputStream} from a {@link PositionedByteRange}. Be sure to update
078   * {@code dst}'s position after writing to the stream.
079   * <p>For example:
080   * <pre>
081   * CodedOutputStream os = outputStreamFromByteRange(dst);
082   * int before = os.spaceLeft(), after, written;
083   * val.writeTo(os);
084   * after = os.spaceLeft();
085   * written = before - after;
086   * dst.setPosition(dst.getPosition() + written);
087   * </pre>
088   */
089  public static CodedOutputStream outputStreamFromByteRange(PositionedByteRange dst) {
090    return CodedOutputStream.newInstance(
091      dst.getBytes(),
092      dst.getOffset() + dst.getPosition(),
093      dst.getRemaining()
094    );
095  }
096}