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 org.apache.hadoop.hbase.util.Order;
021import org.apache.hadoop.hbase.util.PositionedByteRange;
022import org.apache.hadoop.hbase.util.SimplePositionedMutableByteRange;
023import org.apache.yetus.audience.InterfaceAudience;
024
025/**
026 * Wraps an existing {@link DataType} implementation as a fixed-length
027 * version of itself. This has the useful side-effect of turning an existing
028 * {@link DataType} which is not {@code skippable} into a {@code skippable}
029 * variant.
030 */
031@InterfaceAudience.Public
032public class FixedLengthWrapper<T> implements DataType<T> {
033
034  protected final DataType<T> base;
035  protected final int length;
036
037  /**
038   * Create a fixed-length version of the {@code wrapped}.
039   * @param base the {@link DataType} to restrict to a fixed length.
040   * @param length the maximum length (in bytes) for encoded values.
041   */
042  public FixedLengthWrapper(DataType<T> base, int length) {
043    this.base = base;
044    this.length = length;
045  }
046
047  /**
048   * Retrieve the maximum length (in bytes) of encoded values.
049   */
050  public int getLength() {
051    return length;
052  }
053
054  @Override
055  public boolean isOrderPreserving() {
056    return base.isOrderPreserving();
057  }
058
059  @Override
060  public Order getOrder() {
061    return base.getOrder();
062  }
063
064  @Override
065  public boolean isNullable() {
066    return base.isNullable();
067  }
068
069  @Override
070  public boolean isSkippable() {
071    return true;
072  }
073
074  @Override
075  public int encodedLength(T val) {
076    return length;
077  }
078
079  @Override
080  public Class<T> encodedClass() {
081    return base.encodedClass();
082  }
083
084  @Override
085  public int skip(PositionedByteRange src) {
086    src.setPosition(src.getPosition() + this.length);
087    return this.length;
088  }
089
090  @Override
091  public T decode(PositionedByteRange src) {
092    if (src.getRemaining() < length) {
093      throw new IllegalArgumentException("Not enough buffer remaining. src.offset: "
094          + src.getOffset() + " src.length: " + src.getLength() + " src.position: "
095          + src.getPosition() + " max length: " + length);
096    }
097    // create a copy range limited to length bytes. boo.
098    PositionedByteRange b = new SimplePositionedMutableByteRange(length);
099    src.get(b.getBytes());
100    return base.decode(b);
101  }
102
103  @Override
104  public int encode(PositionedByteRange dst, T val) {
105    if (dst.getRemaining() < length) {
106      throw new IllegalArgumentException("Not enough buffer remaining. dst.offset: "
107          + dst.getOffset() + " dst.length: " + dst.getLength() + " dst.position: "
108          + dst.getPosition() + " max length: " + length);
109    }
110    int written = base.encode(dst, val);
111    if (written > length) {
112      throw new IllegalArgumentException("Length of encoded value (" + written
113          + ") exceeds max length (" + length + ").");
114    }
115    // TODO: is the zero-padding appropriate?
116    for (; written < length; written++) {
117      dst.put((byte) 0x00);
118    }
119    return written;
120  }
121}