text: // Copyright 2019 The Dawn Authors
  //
  // 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
  //
  //     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.
  
  #include <array>
  
  #include "common/Assert.h"
  #include "common/BitSetIterator.h"
  #include "dawn_native/Extensions.h"
  
  namespace dawn_native {
      namespace {
  
          struct ExtensionEnumAndInfo {
              Extension extension;
              ExtensionInfo info;
          };
  
          using ExtensionEnumAndInfoList =
              std::array<ExtensionEnumAndInfo, static_cast<size_t>(Extension::EnumCount)>;
  
          static constexpr ExtensionEnumAndInfoList kExtensionNameAndInfoList = {
              {{Extension::TextureCompressionBC,
                {"texture_compression_bc", "Support Block Compressed (BC) texture formats",
                 "https://bugs.chromium.org/p/dawn/issues/detail?id=42"}}}};
  
      }  // anonymous namespace
  
      void ExtensionsSet::EnableExtension(Extension extension) {
          ASSERT(extension != Extension::InvalidEnum);
          const size_t extensionIndex = static_cast<size_t>(extension);
          extensionsBitSet.set(extensionIndex);
      }
  
      bool ExtensionsSet::IsEnabled(Extension extension) const {
          ASSERT(extension != Extension::InvalidEnum);
          const size_t extensionIndex = static_cast<size_t>(extension);
          return extensionsBitSet[extensionIndex];
      }
  
      std::vector<const char*> ExtensionsSet::GetEnabledExtensionNames() const {
          std::vector<const char*> enabledExtensionNames(extensionsBitSet.count());
  
          uint32_t index = 0;
          for (uint32_t i : IterateBitSet(extensionsBitSet)) {
              const char* extensionName = ExtensionEnumToName(static_cast<Extension>(i));
              enabledExtensionNames[index] = extensionName;
              ++index;
          }
          return enabledExtensionNames;
      }
  
      const char* ExtensionEnumToName(Extension extension) {
          ASSERT(extension != Extension::InvalidEnum);
  
          const ExtensionEnumAndInfo& extensionNameAndInfo =
              kExtensionNameAndInfoList[static_cast<size_t>(extension)];
          ASSERT(extensionNameAndInfo.extension == extension);
          return extensionNameAndInfo.info.name;
      }
  
      ExtensionsInfo::ExtensionsInfo() {
          for (size_t index = 0; index < kExtensionNameAndInfoList.size(); ++index) {
              const ExtensionEnumAndInfo& extensionNameAndInfo = kExtensionNameAndInfoList[index];
              ASSERT(index == static_cast<size_t>(extensionNameAndInfo.extension));
              mExtensionNameToEnumMap[extensionNameAndInfo.info.name] =
                  extensionNameAndInfo.extension;
          }
      }
  
      const ExtensionInfo* ExtensionsInfo::GetExtensionInfo(const char* extensionName) const {
          ASSERT(extensionName);
  
          const auto& iter = mExtensionNameToEnumMap.find(extensionName);
          if (iter != mExtensionNameToEnumMap.cend()) {
              return &kExtensionNameAndInfoList[static_cast<size_t>(iter->second)].info;
          }
          return nullptr;
      }
  
      Extension ExtensionsInfo::ExtensionNameToEnum(const char* extensionName) const {
          ASSERT(extensionName);
  
          const auto& iter = mExtensionNameToEnumMap.find(extensionName);
          if (iter != mExtensionNameToEnumMap.cend()) {
              return kExtensionNameAndInfoList[static_cast<size_t>(iter->second)].extension;
          }
          return Extension::InvalidEnum;
      }
  
      ExtensionsSet ExtensionsInfo::ExtensionNamesToExtensionsSet(
          const std::vector<const char*>& requiredExtensions) const {
          ExtensionsSet extensionsSet;
  
          for (const char* extensionName : requiredExtensions) {
              Extension extensionEnum = ExtensionNameToEnum(extensionName);
              ASSERT(extensionEnum != Extension::InvalidEnum);
              extensionsSet.EnableExtension(extensionEnum);
          }
          return extensionsSet;
      }
  
  }  // namespace dawn_native
  