blob: 39afb9c8cbdf3daf13d54510311b40cc3e3ebe96 [file] [log] [blame]
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
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 "tensorflow_lite_support/c/common_utils.h"
#include <string>
#include "absl/status/status.h" // from @com_google_absl
#include "absl/strings/cord.h" // from @com_google_absl
#include "tensorflow_lite_support/cc/common.h"
namespace tflite {
namespace support {
void CreateTfLiteSupportError(enum TfLiteSupportErrorCode code,
const char* message,
TfLiteSupportError** error) {
if (error == nullptr)
return;
*error = new TfLiteSupportError;
(*error)->code = code;
(*error)->message = strdup(message);
}
void CreateTfLiteSupportErrorWithStatus(const absl::Status& status,
TfLiteSupportError** error) {
if (status.ok() || error == nullptr)
return;
// Payload of absl::Status created by the tflite task library stores an
// appropriate value of the enum TfLiteSupportStatus. The integer value
// corresponding to the TfLiteSupportStatus enum stored in the payload is
// extracted here to later map to the appropriate error code to be returned.
// In cases where the enum is not stored in (payload is NULL or the payload
// string cannot be converted to an integer), we set the error code value to
// be 1 (kError of TfLiteErrorCode used in the C library to signify any errors
// not falling into other categories.) Since payload is of type absl::Cord
// that can be type cast into an absl::optional<std::string>, we use the
// std::stoi function to convert it into an integer code if possible.
int generic_error_code = static_cast<int>(kError);
int error_code;
try {
// Try converting payload to integer if payload is not empty. Otherwise
// convert a string signifying generic error code kError to integer.
error_code = std::stoi(static_cast<absl::optional<std::string>>(
status.GetPayload(kTfLiteSupportPayload))
.value_or(std::to_string(generic_error_code)));
} catch (std::invalid_argument& e) {
// If non empty payload string cannot be converted to an integer. Set error
// code to 1(kError).
error_code = generic_error_code;
}
// If error_code is outside the range of enum values possible or is kError, we
// try to map the absl::Status::code() to assign appropriate
// TfLiteSupportErrorCode or kError in default cases. Note: The mapping to
// absl::Status::code() is done to generate a more specific error code than
// kError in cases when the payload can't be mapped to TfLiteSupportStatus.
// This can happen when absl::Status returned by TfLite are in turn returned
// without moodification by TfLite Support Methods.
if (error_code > static_cast<int>(kErrorCodeLast) ||
error_code <= static_cast<int>(kErrorCodeFirst)) {
switch (status.code()) {
case absl::StatusCode::kInternal:
error_code = kInternalError;
break;
case absl::StatusCode::kInvalidArgument:
error_code = kInvalidArgumentError;
break;
case absl::StatusCode::kNotFound:
error_code = kNotFoundError;
break;
default:
error_code = kError;
break;
}
}
// Creates the TfLiteSupportError with the appropriate error
// TfLiteSupportErrorCode and message. TfLiteErrorCode has a one to one
// mapping with TfLiteSupportStatus starting from the value 1(kError) and
// hence will be correctly initialized if directly cast from the integer code
// derived from TfLiteSupportStatus stored in payload. TfLiteErrorCode omits
// kOk = 0 of TfLiteSupportStatus.
//
// Stores a string including absl status code and message(if non empty) as the
// error message See
// https://github.com/abseil/abseil-cpp/blob/master/absl/status/status.h#L514
// for explanation. absl::Status::message() can also be used but not always
// guaranteed to be non empty.
CreateTfLiteSupportError(
static_cast<TfLiteSupportErrorCode>(error_code),
status.ToString(absl::StatusToStringMode::kWithNoExtraData).c_str(),
error);
}
} // namespace support
} // namespace tflite