blob: 013d1152fa2bd4fa5e19f464544757679dbbe981 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GARNET_LIB_UI_GFX_ENGINE_RESOURCE_MAP_H_
#define GARNET_LIB_UI_GFX_ENGINE_RESOURCE_MAP_H_
#include "garnet/lib/ui/gfx/resources/resource.h"
#include "garnet/lib/ui/gfx/resources/variable.h"
#include "garnet/lib/ui/scenic/util/error_reporter.h"
#include <unordered_map>
namespace scenic_impl {
namespace gfx {
class ResourceMap {
public:
explicit ResourceMap(
ErrorReporter* error_reporter = ErrorReporter::Default());
~ResourceMap();
void Clear();
// Attempt to add the resource; return true if successful. Return false if
// the ID is already present in the map, which is left unchanged.
bool AddResource(ResourceId id, ResourcePtr resource);
// Attempt to remove the specified resource. Return true if successful, and
// false if the ID was not present in the map.
bool RemoveResource(ResourceId id);
size_t size() const { return resources_.size(); }
enum class ErrorBehavior { kDontReportErrors, kReportErrors };
// Attempt to find the resource within the map. If it is found, verify that
// it has the correct type, and return it. Return nullptr and report an
// error if it is not found, or if type validation fails.
//
// example:
// ResourceType someResource = map.FindResource<ResourceType>();
template <class ResourceT>
fxl::RefPtr<ResourceT> FindResource(
ResourceId id,
ErrorBehavior report_errors = ErrorBehavior::kReportErrors) {
auto it = resources_.find(id);
if (it == resources_.end()) {
if (report_errors == ErrorBehavior::kReportErrors) {
error_reporter_->ERROR() << "No resource exists with ID " << id;
}
return fxl::RefPtr<ResourceT>();
};
auto resource_ptr = it->second->GetDelegate(ResourceT::kTypeInfo);
if (resource_ptr == nullptr) {
if (report_errors == ErrorBehavior::kReportErrors) {
error_reporter_->ERROR()
<< "Type mismatch for resource ID " << id << ": actual type is "
<< it->second->type_info().name << ", expected a sub-type of "
<< ResourceT::kTypeInfo.name;
}
return fxl::RefPtr<ResourceT>();
}
return fxl::RefPtr<ResourceT>(static_cast<ResourceT*>(resource_ptr));
}
template <class ResourceT>
fxl::RefPtr<ResourceT> FindVariableResource(ResourceId id) {
auto it = resources_.find(id);
if (it == resources_.end()) {
error_reporter_->ERROR() << "No resource exists with ID " << id;
return fxl::RefPtr<ResourceT>();
};
auto resource_ptr = it->second->GetDelegate(Variable::kTypeInfo);
if (resource_ptr == nullptr) {
error_reporter_->ERROR()
<< "Type mismatch for resource ID " << id << ": actual type is "
<< it->second->type_info().name << ", expected a sub-type of "
<< Variable::kTypeInfo.name;
return fxl::RefPtr<ResourceT>();
}
Variable* variable_ptr = static_cast<Variable*>(resource_ptr);
if (ResourceT::ValueType() != variable_ptr->value_type()) {
error_reporter_->ERROR()
<< "Type mismatch for Variable resource ID " << id
<< ": actual type is " << variable_ptr->value_type() << ", expected "
<< ResourceT::ValueType();
return fxl::RefPtr<ResourceT>();
}
return fxl::RefPtr<ResourceT>(static_cast<ResourceT*>(resource_ptr));
}
private:
std::unordered_map<ResourceId, ResourcePtr> resources_;
ErrorReporter* const error_reporter_;
};
} // namespace gfx
} // namespace scenic_impl
#endif // GARNET_LIB_UI_GFX_ENGINE_RESOURCE_MAP_H_