aboutsummaryrefslogblamecommitdiffstats
path: root/library/cpp/yt/error/error_attributes.cpp
blob: fcfe80c414c466b5e608e516d2b362ed29288cdc (plain) (tree)
1
2
3
4
5
6
7
8
9
                             

                       


                                                                                
                                                                      
                           




                                           
 
                                                                                
 


                                     
     

                 
                                                                                        
                             

                                    



                                                                     
 
                                                                     
 












                                                                         
                   
 



                              
                                                     
                              
































                                                                                       





















































                                                                                                                
                  
#include "error_attributes.h"

#include "error.h"
#include "error_code.h"

namespace NYT {

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

std::vector<TErrorAttributes::TKey> TErrorAttributes::ListKeys() const
{
    std::vector<TKey> keys;
    keys.reserve(Map_.size());
    for (const auto& [key, value] : Map_) {
        keys.push_back(key);
    }
    return keys;
}

std::vector<TErrorAttributes::TKeyValuePair> TErrorAttributes::ListPairs() const
{
    std::vector<TKeyValuePair> pairs;
    pairs.reserve(Map_.size());
    for (const auto& pair : Map_) {
        pairs.push_back(pair);
    }
    return pairs;
}

std::optional<TErrorAttribute::TValue> TErrorAttributes::FindValue(TStringBuf key) const
{
    auto it = Map_.find(key);
    return it == Map_.end()
        ? std::nullopt
        : std::optional(it->second);
}

void TErrorAttributes::SetValue(const TKey& key, const TValue& value)
{
    Map_[key] = value;
}

void TErrorAttributes::SetAttribute(const TErrorAttribute& attribute)
{
    SetValue(attribute.Key, attribute.Value);
}

bool TErrorAttributes::Remove(const TKey& key)
{
    return Map_.erase(key) > 0;
}

TErrorAttributes::TValue TErrorAttributes::GetValue(TStringBuf key) const
{
    auto result = FindValue(key);
    if (!result) {
        ThrowNoSuchAttributeException(key);
    }
    return *result;
}

void TErrorAttributes::Clear()
{
    Map_.clear();
}

bool TErrorAttributes::Contains(TStringBuf key) const
{
    return Map_.contains(key);
}

bool operator == (const TErrorAttributes& lhs, const TErrorAttributes& rhs)
{
    auto lhsPairs = lhs.ListPairs();
    auto rhsPairs = rhs.ListPairs();
    if (lhsPairs.size() != rhsPairs.size()) {
        return false;
    }

    std::sort(lhsPairs.begin(), lhsPairs.end(), [] (const auto& lhs, const auto& rhs) {
        return lhs.first < rhs.first;
    });
    std::sort(rhsPairs.begin(), rhsPairs.end(), [] (const auto& lhs, const auto& rhs) {
        return lhs.first < rhs.first;
    });

    for (auto index = 0; index < std::ssize(lhsPairs); ++index) {
        if (lhsPairs[index].first != rhsPairs[index].first) {
            return false;
        }
    }

    for (auto index = 0; index < std::ssize(lhsPairs); ++index) {
        if (lhsPairs[index].second != rhsPairs[index].second) {
            return false;
        }
    }

    return true;
}

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

namespace {

bool IsSpecialCharacter(char ch)
{
    return ch == '\\' || ch == '/' || ch == '@' || ch == '*' || ch == '&' || ch == '[' || ch == '{';
}

// AppendYPathLiteral.
void DoFormatAttributeKey(TStringBuilderBase* builder, TStringBuf value)
{
    constexpr char asciiBegin = 32;
    constexpr char asciiEnd = 127;
    builder->Preallocate(value.length() + 16);
    for (unsigned char ch : value) {
        if (IsSpecialCharacter(ch)) {
            builder->AppendChar('\\');
            builder->AppendChar(ch);
        } else if (ch < asciiBegin || ch > asciiEnd) {
            builder->AppendString(TStringBuf("\\x"));
            builder->AppendChar(IntToHexLowercase[ch >> 4]);
            builder->AppendChar(IntToHexLowercase[ch & 0xf]);
        } else {
            builder->AppendChar(ch);
        }
    }
}

} // namespace

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

[[noreturn]] void TErrorAttributes::ThrowCannotParseAttributeException(TStringBuf key, const std::exception& ex)
{
    THROW_ERROR_EXCEPTION(
        "Error parsing attribute %Qv",
        key)
        << ex;
}

[[noreturn]] void TErrorAttributes::ThrowNoSuchAttributeException(TStringBuf key)
{
    auto formatAttributeKey = [] (auto key) {
        TStringBuilder builder;
        DoFormatAttributeKey(&builder, key);
        return builder.Flush();
    };

    THROW_ERROR_EXCEPTION(
        /*NYTree::EErrorCode::ResolveError*/ TErrorCode{500},
        "Attribute %Qv is not found",
        formatAttributeKey(key));
}

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

} // namespace NYT