Создать boost :: uuids :: uuid из boost :: compute :: detail :: sha1

Я пытаюсь сгенерировать повышение :: UUID, :: UUID от повышение :: :: вычислить детали :: sha1 в этом случае:

#include <iostream>
#include "boost/uuid/uuid.hpp"#include "boost/uuid/uuid_io.hpp"#include "boost/uuid/string_generator.hpp"#include "boost/compute/detail/sha1.hpp"
int main(int argc, char* argv[])
{
try
{
boost::compute::detail::sha1 sha1("b888e35f9edf3794760392e1066d69-f43d-452e-8475-a09bae9a2e8500000000-0000-0000-0000-000000000000");
std::string str = sha1;
boost::uuids::uuid uuid = boost::uuids::string_generator()(str); // ERROR HERE!!
}
catch (std::exception& e)
{
std::cerr << "Error occurred: " << e.what() << std::endl;
}

return 0;
}

Но этот код не работает с ошибкой Error occurred: invalid uuid string (См выше)

Я использую Visual Studio 2017, Boost 1.67

Где моя ошибка? Как создать boost :: uuids :: uuid из boost :: compute :: detail :: sha1

PS: этот код работал на предыдущих версиях буста.

1

Решение

Правильный, поддерживаемый подход к получению UUID из хэша SHA1 произвольной строки заключается в следующем:

#include <string_view>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/name_generator_sha1.hpp>

boost::uuids::uuid uuid_from_string(std::string_view const input) {
static constexpr boost::uuids::uuid ns_id{}; // †null root, change as necessary
return boost::uuids::name_generator_sha1{ns_id}(input.data(), input.size());
}

Демо онлайн

(std::string_view используется для экспозиции; использование std::string или же char const* или что угодно, если это не подходит для вас.)

Пока это правильный Подход есть два важных замечания:

  1. Согласно RFC 4122, вам нужно предоставить пространство имен для вашего UUID; в основном это соль для вашего хэша SHA1. Существуют предопределенные пространства имен для DNS-имен, URL-адресов, ISO-идентификаторов ISO и отличительных имен X.500, но поскольку ваши входные данные не соответствуют ни одному из тех, которые вам нужны для определения ваших собственных; как указано в строке, помеченной †, для экспозиции здесь используется пустое пространство имен. Более подробное объяснение пространств имен UUID можно найти в этом ответе SO: Генерация v5 UUID. Что такое имя и пространство имен?

  2. Вывод этого кода будет полностью отличаться от вывода кода в вашем вопросе; тогда и только тогда вам нужен вывод, чтобы соответствовать старому коду, вы можете сделать следующее:

    #include <cstring>
    #include <string_view>
    #include <boost/endian/conversion.hpp>
    #include <boost/uuid/uuid.hpp>
    #include <boost/uuid/detail/sha1.hpp>
    
    boost::uuids::uuid uuid_from_string_old(std::string_view const input) {
    boost::uuids::detail::sha1::digest_type digest;
    {
    boost::uuids::detail::sha1 h;
    h.process_bytes(input.data(), input.size());
    h.get_digest(digest);
    }
    
    boost::uuids::uuid ret;
    auto p = ret.begin();
    for (std::size_t i{}; i != 4; p += 4, ++i) {
    auto const d = boost::endian::native_to_big(digest[i]);
    std::memcpy(p, &d, 4);
    }
    return ret;
    }
    

    Демо онлайн

    Это дает тот же результат, что видно из это демо используя старый код с Boost 1.65.1. Это идет вразрез с моей прокомментированной политикой никогда напрямую не использовать чужие detail namespace, но если вы не можете найти магический идентификатор пространства имен (если он существует), это единственный подход с использованием Boost, о котором я знаю. Нотабене это исправляет ошибку в старом коде Boost для машин с прямым порядком байтов; если вам нужно сохранить эту ошибку, измените вызов на boost::endian::native_to_big вызывать boost::endian::endian_reverse вместо.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]