// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://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.

#include "src/decoder/physical_astc_block.h"
#include "src/base/math_utils.h"
#include "src/base/optional.h"
#include "src/base/uint128.h"
#include "src/decoder/integer_sequence_codec.h"

#include <array>
#include <cmath>

namespace astc_codec {

namespace {

static_assert(static_cast<int>(ColorEndpointMode::kNumColorEndpointModes) == 16,
              "There are only sixteen color endpoint modes defined in the "
              "ASTC specification. If this is false, then the enum may be "
              "incorrect.");

constexpr int kASTCBlockSizeBits = 128;
constexpr int kASTCBlockSizeBytes = kASTCBlockSizeBits / 8;
constexpr uint32_t kVoidExtentMaskBits = 9;
constexpr uint32_t kVoidExtentMask = 0x1FC;
constexpr int kWeightGridMinBitLength = 24;
constexpr int kWeightGridMaxBitLength = 96;
constexpr int kMaxNumPartitions = 4;
constexpr int kMaxNumWeights = 64;

// These are the overall block modes defined in table C.2.8.  There are 10
// weight grid encoding schemes + void extent.
enum class BlockMode {
  kB4_A2,
  kB8_A2,
  kA2_B8,
  kA2_B6,
  kB2_A2,
  k12_A2,
  kA2_12,
  k6_10,
  k10_6,
  kA6_B6,
  kVoidExtent,
};

struct WeightGridProperties {
  int width;
  int height;
  int range;
};

// Local function prototypes
base::Optional<BlockMode> DecodeBlockMode(const base::UInt128 astc_bits);
base::Optional<WeightGridProperties> DecodeWeightProps(
    const base::UInt128 astc_bits, std::string* error);
std::array<int, 4> DecodeVoidExtentCoords(const base::UInt128 astc_bits);
bool DecodeDualPlaneBit(const base::UInt128 astc_bits);
int DecodeNumPartitions(const base::UInt128 astc_bits);
int DecodeNumWeightBits(const base::UInt128 astc_bits);
int DecodeDualPlaneBitStartPos(const base::UInt128 astc_bits);
ColorEndpointMode DecodeEndpointMode(const base::UInt128 astc_bits,
                                     int partition);
int DecodeNumColorValues(const base::UInt128 astc_bits);

// Returns the block mode, if it's valid.
base::Optional<BlockMode> DecodeBlockMode(const base::UInt128 astc_bits) {
  using Result = base::Optional<BlockMode>;
  const uint64_t low_bits = astc_bits.LowBits();
  if (base::GetBits(low_bits, 0, kVoidExtentMaskBits) == kVoidExtentMask) {
    return Result(BlockMode::kVoidExtent);
  }

  if (base::GetBits(low_bits, 0, 2) != 0) {
    const uint64_t mode_bits = base::GetBits(low_bits, 2, 2);
    switch (mode_bits) {
      case 0: return Result(BlockMode::kB4_A2);
      case 1: return Result(BlockMode::kB8_A2);
      case 2: return Result(BlockMode::kA2_B8);
      case 3: return base::GetBits(low_bits, 8, 1) ?
          Result(BlockMode::kB2_A2) : Result(BlockMode::kA2_B6);
    }
  } else {
    const uint64_t mode_bits = base::GetBits(low_bits, 5, 4);
    if ((mode_bits & 0xC) == 0x0) {
      if (base::GetBits(low_bits, 0, 4) == 0) {
        // Reserved.
        return Result();
      } else {
        return Result(BlockMode::k12_A2);
      }
    } else if ((mode_bits & 0xC) == 0x4) {
      return Result(BlockMode::kA2_12);
    } else if (mode_bits == 0xC) {
      return Result(BlockMode::k6_10);
    } else if (mode_bits == 0xD) {
      return Result(BlockMode::k10_6);
    } else if ((mode_bits & 0xC) == 0x8) {
      return Result(BlockMode::kA6_B6);
    }
  }

  return Result();
}

base::Optional<WeightGridProperties> DecodeWeightProps(
    const base::UInt128 astc_bits, std::string* error) {
  auto block_mode = DecodeBlockMode(astc_bits);
  if (!block_mode) {
    *error = "Reserved block mode";
    return {};
  }

  // The dimensions of the weight grid and their range
  WeightGridProperties props;

  // Determine the weight extents based on the block mode
  const uint32_t low_bits =
      static_cast<uint32_t>(astc_bits.LowBits() & 0xFFFFFFFF);
  switch (block_mode.value()) {
    case BlockMode::kB4_A2: {
      int a = base::GetBits(low_bits, 5, 2);
      int b = base::GetBits(low_bits, 7, 2);
      props.width = b + 4;
      props.height = a + 2;
    }
    break;

    case BlockMode::kB8_A2: {
      int a = base::GetBits(low_bits, 5, 2);
      int b = base::GetBits(low_bits, 7, 2);
      props.width = b + 8;
      props.height = a + 2;
    }
    break;

    case BlockMode::kA2_B8: {
      int a = base::GetBits(low_bits, 5, 2);
      int b = base::GetBits(low_bits, 7, 2);
      props.width = a + 2;
      props.height = b + 8;
    }
    break;

    case BlockMode::kA2_B6: {
      int a = base::GetBits(low_bits, 5, 2);
      int b = base::GetBits(low_bits, 7, 1);
      props.width = a + 2;
      props.height = b + 6;
    }
    break;

    case BlockMode::kB2_A2: {
      int a = base::GetBits(low_bits, 5, 2);
      int b = base::GetBits(low_bits, 7, 1);
      props.width = b + 2;
      props.height = a + 2;
    }
    break;

    case BlockMode::k12_A2: {
      int a = base::GetBits(low_bits, 5, 2);
      props.width = 12;
      props.height = a + 2;
    }
    break;

    case BlockMode::kA2_12: {
      int a = base::GetBits(low_bits, 5, 2);
      props.width = a + 2;
      props.height = 12;
    }
    break;

    case BlockMode::k6_10: {
      props.width = 6;
      props.height = 10;
    }
    break;

    case BlockMode::k10_6: {
      props.width = 10;
      props.height = 6;
    }
    break;

    case BlockMode::kA6_B6: {
      int a = base::GetBits(low_bits, 5, 2);
      int b = base::GetBits(low_bits, 9, 2);
      props.width = a + 6;
      props.height = b + 6;
    }
    break;

    // Void extent blocks have no weight grid.
    case BlockMode::kVoidExtent:
      *error = "Void extent block has no weight grid";
      return {};

    // We have a valid block mode which isn't a void extent? We
    // should be able to decode the weight grid dimensions.
    default:
      assert(false && "Error decoding weight grid");
      *error = "Internal error";
      return {};
  }

  // Determine the weight range based on the block mode
  uint32_t r = base::GetBits(low_bits, 4, 1);
  switch (block_mode.value()) {
    case BlockMode::kB4_A2:
    case BlockMode::kB8_A2:
    case BlockMode::kA2_B8:
    case BlockMode::kA2_B6:
    case BlockMode::kB2_A2: {
      r |= base::GetBits(low_bits, 0, 2) << 1;
    }
    break;

    case BlockMode::k12_A2:
    case BlockMode::kA2_12:
    case BlockMode::k6_10:
    case BlockMode::k10_6:
    case BlockMode::kA6_B6:  {
      r |= base::GetBits(low_bits, 2, 2) << 1;
    }
    break;

    // We have a valid block mode which doesn't have weights? We
    // should have caught this earlier.
    case BlockMode::kVoidExtent:
    default:
      assert(false && "Error decoding weight grid");
      *error = "Internal error";
      return {};
  }

  // Decode the range...
  // High bit is in bit 9 unless we're using a particular block mode
  uint32_t h = base::GetBits(low_bits, 9, 1);
  if (block_mode == BlockMode::kA6_B6) {
    h = 0;
  }

  // Figure out the range of the weights (Table C.2.7)
  constexpr std::array<int, 16> kWeightRanges = {{
      -1, -1, 1, 2, 3, 4, 5, 7, -1, -1, 9, 11, 15, 19, 23, 31
    }};

  assert(((h << 3) | r) < kWeightRanges.size());

  props.range = kWeightRanges.at((h << 3) | r);
  if (props.range < 0) {
    *error = "Reserved range for weight bits";
    return {};
  }

  // Error checking -- do we have too many weights?
  int num_weights = props.width * props.height;
  if (DecodeDualPlaneBit(astc_bits)) {
    num_weights *= 2;
  }

  if (kMaxNumWeights < num_weights) {
    *error = "Too many weights specified";
    return {};
  }

  // Do we have too many weight bits?
  const int bit_count =
      IntegerSequenceCodec::GetBitCountForRange(num_weights, props.range);

  if (bit_count < kWeightGridMinBitLength) {
    *error = "Too few bits required for weight grid";
    return {};
  }

  if (kWeightGridMaxBitLength < bit_count) {
    *error = "Too many bits required for weight grid";
    return {};
  }

  return props;
}

// Returns the four 13-bit integers that define the range of texture
// coordinates present in a void extent block as defined in Section
// C.2.23 of the specification. The coordinates returned are of
// the form (min_s, max_s, min_t, max_t)
std::array<int, 4> DecodeVoidExtentCoords(const base::UInt128 astc_bits) {
  const uint64_t low_bits = astc_bits.LowBits();

  std::array<int, 4> coords;
  for (int i = 0; i < 4; ++i) {
    coords[i] = static_cast<int>(base::GetBits(low_bits, 12 + 13 * i, 13));
  }

  return coords;
}

bool DecodeDualPlaneBit(const base::UInt128 astc_bits) {
  base::Optional<BlockMode> block_mode = DecodeBlockMode(astc_bits);

  // Void extent blocks certainly aren't dual-plane.
  if (block_mode == BlockMode::kVoidExtent) {
    return false;
  }

  // One special block mode doesn't have any dual plane bit
  if (block_mode == BlockMode::kA6_B6) {
    return false;
  }

  // Otherwise, dual plane is determined by the 10th bit.
  constexpr int kDualPlaneBitPosition = 10;
  return base::GetBits(astc_bits, kDualPlaneBitPosition, 1) != 0;
}

int DecodeNumPartitions(const base::UInt128 astc_bits) {
  constexpr int kNumPartitionsBitPosition = 11;
  constexpr int kNumPartitionsBitLength = 2;

  // Non-void extent blocks
  const uint64_t low_bits = astc_bits.LowBits();
  const int num_partitions = 1 + static_cast<int>(
      base::GetBits(low_bits,
                    kNumPartitionsBitPosition,
                    kNumPartitionsBitLength));
  assert(num_partitions > 0);
  assert(num_partitions <= kMaxNumPartitions);

  return num_partitions;
}

int DecodeNumWeightBits(const base::UInt128 astc_bits) {
  std::string error;
  auto maybe_weight_props = DecodeWeightProps(astc_bits, &error);
  if (!maybe_weight_props.hasValue()) {
    return 0;  // No weights? No weight bits...
  }

  const auto weight_props = maybe_weight_props.value();

  // Figure out the number of weights
  int num_weights = weight_props.width * weight_props.height;
  if (DecodeDualPlaneBit(astc_bits)) {
    num_weights *= 2;
  }

  // The number of bits is determined by the number of values
  // that are going to be encoded using the given ise_counts.
  return IntegerSequenceCodec::GetBitCountForRange(
      num_weights, weight_props.range);
}

// Returns the number of bits after the weight data used to
// store additional CEM bits.
int DecodeNumExtraCEMBits(const base::UInt128 astc_bits) {
  const int num_partitions = DecodeNumPartitions(astc_bits);

  // Do we only have one partition?
  if (num_partitions == 1) {
    return 0;
  }

  // Do we have a shared CEM?
  constexpr int kSharedCEMBitPosition = 23;
  constexpr int kSharedCEMBitLength = 2;
  const base::UInt128 shared_cem =
      base::GetBits(astc_bits, kSharedCEMBitPosition, kSharedCEMBitLength);
  if (shared_cem == 0) {
    return 0;
  }

  const std::array<int, 4> extra_cem_bits_for_partition = {{ 0, 2, 5, 8 }};
  return extra_cem_bits_for_partition[num_partitions - 1];
}

// Returns the starting position of the dual plane channel. This comes
// before the weight data and extra CEM bits.
int DecodeDualPlaneBitStartPos(const base::UInt128 astc_bits) {
  const int start_pos = kASTCBlockSizeBits
      - DecodeNumWeightBits(astc_bits)
      - DecodeNumExtraCEMBits(astc_bits);

  if (DecodeDualPlaneBit(astc_bits)) {
    return start_pos - 2;
  } else {
    return start_pos;
  }
}

// Decodes a CEM mode based on the partition number.
ColorEndpointMode DecodeEndpointMode(const base::UInt128 astc_bits,
                                     int partition) {
  int num_partitions = DecodeNumPartitions(astc_bits);
  assert(partition >= 0);
  assert(partition < num_partitions);

  // Do we only have one partition?
  uint64_t low_bits = astc_bits.LowBits();
  if (num_partitions == 1) {
    uint64_t cem = base::GetBits(low_bits, 13, 4);
    return static_cast<ColorEndpointMode>(cem);
  }

  // More than one partition ... do we have a shared CEM?
  if (DecodeNumExtraCEMBits(astc_bits) == 0) {
    const uint64_t shared_cem = base::GetBits(low_bits, 25, 4);
    return static_cast<ColorEndpointMode>(shared_cem);
  }

  // More than one partition and no shared CEM...
  uint64_t cem = base::GetBits(low_bits, 23, 6);
  const int base_cem = static_cast<int>(((cem & 0x3) - 1) * 4);
  cem >>= 2;  // Skip the base CEM bits

  // The number of extra CEM bits at the end of the weight grid is
  // determined by the number of partitions and what the base cem mode is...
  const int num_extra_cem_bits = DecodeNumExtraCEMBits(astc_bits);
  const int extra_cem_start_pos = kASTCBlockSizeBits
      - num_extra_cem_bits
      - DecodeNumWeightBits(astc_bits);

  base::UInt128 extra_cem =
      base::GetBits(astc_bits, extra_cem_start_pos, num_extra_cem_bits);
  cem |= extra_cem.LowBits() << 4;

  // Decode C and M per Figure C.4
  int c = -1, m = -1;
  for (int i = 0; i < num_partitions; ++i) {
    if (i == partition) {
      c = cem & 0x1;
    }
    cem >>= 1;
  }

  for (int i = 0; i < num_partitions; ++i) {
    if (i == partition) {
      m = cem & 0x3;
    }
    cem >>= 2;
  }

  assert(c >= 0);
  assert(m >= 0);

  // Compute the mode based on C and M
  const int mode = base_cem + 4 * c + m;
  assert(mode < static_cast<int>(ColorEndpointMode::kNumColorEndpointModes));
  return static_cast<ColorEndpointMode>(mode);
}

int DecodeNumColorValues(const base::UInt128 astc_bits) {
  int num_color_values = 0;
  auto num_partitions = DecodeNumPartitions(astc_bits);
  for (int i = 0; i < num_partitions; ++i) {
    ColorEndpointMode endpoint_mode = DecodeEndpointMode(astc_bits, i);
    num_color_values += NumColorValuesForEndpointMode(endpoint_mode);
  }

  return num_color_values;
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////

static_assert(sizeof(PhysicalASTCBlock) == PhysicalASTCBlock::kSizeInBytes,
              "The size of the struct should be the size of the block so that"
              "we can effectively use them contiguously in memory.");

PhysicalASTCBlock::PhysicalASTCBlock(const base::UInt128 astc_block)
    : astc_bits_(astc_block) {}

PhysicalASTCBlock::PhysicalASTCBlock(const std::string& encoded_block)
    : astc_bits_([&encoded_block]() {
        assert(encoded_block.size() == PhysicalASTCBlock::kSizeInBytes);
        base::UInt128 astc_bits = 0;
        int shift = 0;
        for (const unsigned char c : encoded_block) {
          astc_bits |= base::UInt128(static_cast<uint64_t>(c)) << shift;
          shift += 8;
        }
        return astc_bits;
      }())
{ }

base::Optional<std::string> PhysicalASTCBlock::IsIllegalEncoding() const {
  // If the block is not a void extent block, then it must have
  // weights specified. DecodeWeightProps will return the weight specifications
  // if they exist and are legal according to C.2.24, and will otherwise be
  // empty.
  base::Optional<BlockMode> block_mode = DecodeBlockMode(astc_bits_);
  if (block_mode != BlockMode::kVoidExtent) {
    std::string error;
    auto maybe_weight_props = DecodeWeightProps(astc_bits_, &error);
    if (!maybe_weight_props.hasValue()) {
      return error;
    }
  }

  // Check void extent blocks...
  if (block_mode == BlockMode::kVoidExtent) {
    // ... for reserved bits incorrectly set
    if (base::GetBits(astc_bits_, 10, 2) != 0x3) {
      return std::string("Reserved bits set for void extent block");
    }

    // ... for incorrectly defined texture coordinates
    std::array<int, 4> coords = DecodeVoidExtentCoords(astc_bits_);

    bool coords_all_1s = true;
    for (const auto coord : coords) {
      coords_all_1s &= coord == ((1 << 13) - 1);
    }

    if (!coords_all_1s && (coords[0] >= coords[1] || coords[2] >= coords[3])) {
      return std::string("Void extent texture coordinates are invalid");
    }
  }

  // If the number of color values exceeds a threshold and it isn't a void
  // extent block then we've run into an error
  if (block_mode != BlockMode::kVoidExtent) {
    int num_color_vals = DecodeNumColorValues(astc_bits_);
    if (num_color_vals > 18) {
      return std::string("Too many color values");
    }

    // The maximum number of available color bits is the number of
    // bits between the dual plane bits and the base CEM. This must
    // be larger than a threshold defined in C.2.24.

    // Dual plane bit starts after weight bits and CEM
    const int num_partitions = DecodeNumPartitions(astc_bits_);
    const int dual_plane_start_pos = DecodeDualPlaneBitStartPos(astc_bits_);
    const int color_start_bit = (num_partitions == 1) ? 17 : 29;

    const int required_color_bits = ((13 * num_color_vals) + 4) / 5;
    const int available_color_bits = dual_plane_start_pos - color_start_bit;
    if (available_color_bits < required_color_bits) {
      return std::string("Not enough color bits");
    }

    // If we have four partitions and a dual plane then we have a problem.
    if (num_partitions == 4 && DecodeDualPlaneBit(astc_bits_)) {
      return std::string("Both four partitions and dual plane specified");
    }
  }

  // Otherwise we're OK
  return { };
}

bool PhysicalASTCBlock::IsVoidExtent() const {
  // If it's an error block, it's not a void extent block.
  if (IsIllegalEncoding()) {
    return false;
  }

  return DecodeBlockMode(astc_bits_) == BlockMode::kVoidExtent;
}

base::Optional<std::array<int, 4>> PhysicalASTCBlock::VoidExtentCoords() const {
  if (IsIllegalEncoding() || !IsVoidExtent()) {
    return { };
  }

  // If void extent coords are all 1's then these are not valid void extent
  // coords
  const uint64_t ve_mask = 0xFFFFFFFFFFFFFDFFULL;
  const uint64_t const_blk_mode = 0xFFFFFFFFFFFFFDFCULL;
  if ((ve_mask & astc_bits_.LowBits()) == const_blk_mode) {
    return {};
  }

  return DecodeVoidExtentCoords(astc_bits_);
}

bool PhysicalASTCBlock::IsDualPlane() const {
  // If it's an error block, then we aren't a dual plane block
  if (IsIllegalEncoding()) {
    return false;
  }

  return DecodeDualPlaneBit(astc_bits_);
}

// Returns the number of weight bits present in this block
base::Optional<int> PhysicalASTCBlock::NumWeightBits() const {
  // If it's an error block, then we have no weight bits.
  if (IsIllegalEncoding()) return { };

  // If it's a void extent block, we have no weight bits
  if (IsVoidExtent()) return { };

  return DecodeNumWeightBits(astc_bits_);
}

base::Optional<int> PhysicalASTCBlock::WeightStartBit() const {
  if (IsIllegalEncoding()) return { };
  if (IsVoidExtent()) return { };

  return kASTCBlockSizeBits - DecodeNumWeightBits(astc_bits_);
}

base::Optional<std::array<int, 2>> PhysicalASTCBlock::WeightGridDims() const {
  std::string error;
  auto weight_props = DecodeWeightProps(astc_bits_, &error);

  if (!weight_props.hasValue()) return { };
  if (IsIllegalEncoding()) return { };

  const auto props = weight_props.value();
  return {{{ props.width, props.height }}};
}

base::Optional<int> PhysicalASTCBlock::WeightRange() const {
  std::string error;
  auto weight_props = DecodeWeightProps(astc_bits_, &error);

  if (!weight_props.hasValue()) return { };
  if (IsIllegalEncoding()) return { };

  return weight_props.value().range;
}

base::Optional<int> PhysicalASTCBlock::DualPlaneChannel() const {
  if (!IsDualPlane()) return { };

  int dual_plane_start_pos = DecodeDualPlaneBitStartPos(astc_bits_);
  auto plane_bits = base::GetBits(astc_bits_, dual_plane_start_pos, 2);
  return base::Optional<int>(static_cast<int>(plane_bits.LowBits()));
}

base::Optional<int> PhysicalASTCBlock::ColorStartBit() const {
  if (IsVoidExtent()) {
    return 64;
  }

  auto num_partitions = NumPartitions();
  if (!num_partitions) return { };

  return (num_partitions == 1) ? 17 : 29;
}

base::Optional<int> PhysicalASTCBlock::NumColorValues() const {
  // If we have a void extent block, then we have four color values
  if (IsVoidExtent()) {
    return 4;
  }

  // If we have an illegal encoding, then we have no color values
  if (IsIllegalEncoding()) return { };

  return DecodeNumColorValues(astc_bits_);
}

void PhysicalASTCBlock::GetColorValuesInfo(int* const color_bits,
                                           int* const color_range) const {
  // Figure out the range possible for the number of values we have...
  const int dual_plane_start_pos = DecodeDualPlaneBitStartPos(astc_bits_);
  const int max_color_bits = dual_plane_start_pos - ColorStartBit().value();
  const int num_color_values = NumColorValues().value();
  for (int range = 255; range > 0; --range) {
    const int bitcount =
        IntegerSequenceCodec::GetBitCountForRange(num_color_values, range);
    if (bitcount <= max_color_bits) {
      if (color_bits != nullptr) {
        *color_bits = bitcount;
      }

      if (color_range != nullptr) {
        *color_range = range;
      }
      return;
    }
  }

  assert(false &&
         "This means that even if we have a range of one there aren't "
         "enough bits to store the color values, and our encoding is "
         "illegal.");
}

base::Optional<int> PhysicalASTCBlock::NumColorBits() const {
  if (IsIllegalEncoding()) return { };

  if (IsVoidExtent()) {
    return 64;
  }

  int color_bits;
  GetColorValuesInfo(&color_bits, nullptr);
  return color_bits;
}

base::Optional<int> PhysicalASTCBlock::ColorValuesRange() const {
  if (IsIllegalEncoding()) return { };

  if (IsVoidExtent()) {
    return (1 << 16) - 1;
  }

  int color_range;
  GetColorValuesInfo(nullptr, &color_range);
  return color_range;
}

base::Optional<int> PhysicalASTCBlock::NumPartitions() const {
  // Error blocks have no partitions
  if (IsIllegalEncoding()) return { };

  // Void extent blocks have no partitions either
  if (DecodeBlockMode(astc_bits_) == BlockMode::kVoidExtent) {
    return { };
  }

  // All others have some number of partitions
  return DecodeNumPartitions(astc_bits_);
}

base::Optional<int> PhysicalASTCBlock::PartitionID() const {
  auto num_partitions = NumPartitions();
  if (!num_partitions || num_partitions == 1) return { };

  const uint64_t low_bits = astc_bits_.LowBits();
  return static_cast<int>(base::GetBits(low_bits, 13, 10));
}

base::Optional<ColorEndpointMode> PhysicalASTCBlock::GetEndpointMode(
    int partition) const {
  // Error block?
  if (IsIllegalEncoding()) return { };

  // Void extent blocks have no endpoint modes
  if (DecodeBlockMode(astc_bits_) == BlockMode::kVoidExtent) {
    return { };
  }

  // Do we even have a CEM for this partition?
  if (partition < 0 || DecodeNumPartitions(astc_bits_) <= partition) {
    return { };
  }

  return DecodeEndpointMode(astc_bits_, partition);
}

}  // namespace astc_codec
