diff options
author | Claudius "keldu" Holeksa <mail@keldu.de> | 2024-01-15 17:04:16 +0100 |
---|---|---|
committer | Claudius "keldu" Holeksa <mail@keldu.de> | 2024-01-15 17:04:16 +0100 |
commit | d94c31fee53c3c7df981cf44a54dd722d7fc122c (patch) | |
tree | 4f74d240d8db6dc12a8ec1832dfac13eb96dc21b | |
parent | 830e341a9357556dd15a62b1ce1c74056a506987 (diff) |
codec: hash functionality added
-rw-r--r-- | modules/codec/c++/schema.h | 59 | ||||
-rw-r--r-- | modules/codec/c++/schema_hash.h | 104 | ||||
-rw-r--r-- | modules/codec/tests/schema.cpp | 13 |
3 files changed, 79 insertions, 97 deletions
diff --git a/modules/codec/c++/schema.h b/modules/codec/c++/schema.h index 576f378..4549916 100644 --- a/modules/codec/c++/schema.h +++ b/modules/codec/c++/schema.h @@ -6,7 +6,9 @@ namespace saw { namespace schema { // NOLINTBEGIN -template <typename T, string_literal Literal> struct Member {}; +template <typename T, string_literal Literal> struct Member { + static constexpr string_literal name = "Member"; +}; template <typename... T> struct Struct { static_assert( @@ -15,7 +17,9 @@ template <typename... T> struct Struct { }; template <typename... V, string_literal... K> -struct Struct<Member<V, K>...> {}; +struct Struct<Member<V, K>...> { + static constexpr string_literal name = "Struct"; +}; template <typename... T> struct Union { static_assert( @@ -24,13 +28,21 @@ template <typename... T> struct Union { }; template <typename... V, string_literal... K> -struct Union<Member<V, K>...> {}; +struct Union<Member<V, K>...> { + static constexpr string_literal name = "Union"; +}; -template <typename T, size_t Dim = 1> struct Array {}; +template <typename T, size_t Dim = 1> struct Array { + static constexpr string_literal name = "Array"; +}; -template<typename T, size_t... S> struct FixedArray {}; +template<typename T, size_t... S> struct FixedArray { + static constexpr string_literal name = "FixedArray"; +}; -template <typename... T> struct Tuple {}; +template <typename... T> struct Tuple { + static constexpr string_literal name = "Tuple"; +}; /** * This acts as a separator of different encodings being mashed together @@ -43,14 +55,24 @@ template <typename... T> struct Tuple {}; * data<WrappedExample, encode::Json> ex_data; */ template <typename T, typename Enc> -class Wrapper {}; +class Wrapper { + static constexpr string_literal name = "Wrapper"; +}; -struct String {}; +struct String { + static constexpr string_literal name = "String"; +}; -struct SignedInteger {}; -struct UnsignedInteger {}; -struct FloatingPoint {}; +struct SignedInteger { + static constexpr string_literal name = "SignedInteger"; +}; +struct UnsignedInteger { + static constexpr string_literal name = "UnsignedInteger"; +}; +struct FloatingPoint { + static constexpr string_literal name = "FloatingPoint"; +}; template <class T, size_t N> struct Primitive { static_assert(((std::is_same_v<T, SignedInteger> || @@ -58,6 +80,7 @@ template <class T, size_t N> struct Primitive { N == 4 || N == 8)) || (std::is_same_v<T, FloatingPoint> && (N == 4 || N == 8)), "Primitive Type is not supported"); + static constexpr string_literal name = "Primitive"; }; using Int8 = Primitive<SignedInteger, 1>; @@ -77,7 +100,9 @@ using Float64 = Primitive<FloatingPoint, 8>; * Classes allowing to distinguish Ints from VarInts */ template<typename T, std::size_t MaxLen> -struct VariableLengthPrimitive {}; +struct VariableLengthPrimitive { + static constexpr string_literal name = "VariableLengthPrimitive"; +}; using VarInt = VariableLengthPrimitive<SignedInteger, 5>; using VarLong = VariableLengthPrimitive<SignedInteger, 10>; @@ -86,16 +111,22 @@ using VarLong = VariableLengthPrimitive<SignedInteger, 10>; * Classes enabling Rpc calls */ template <class Request, class Response> -struct Function {}; +struct Function { + static constexpr string_literal name = "Function"; +}; template <class... T> struct Interface { static_assert( always_false<T...>, "This schema template doesn't support this type of template argument"); + + static constexpr string_literal name = "Interface"; }; template <class... Requests, class... Responses, string_literal... Names> -struct Interface<Member<Function<Requests, Responses>,Names>...> {}; +struct Interface<Member<Function<Requests, Responses>,Names>...> { + static constexpr string_literal name = "Interface"; +}; // NOLINTEND } // namespace schema diff --git a/modules/codec/c++/schema_hash.h b/modules/codec/c++/schema_hash.h index 5690166..a7f482f 100644 --- a/modules/codec/c++/schema_hash.h +++ b/modules/codec/c++/schema_hash.h @@ -1,105 +1,43 @@ #pragma once +#include <forstio/string_literal.h> #include "schema.h" +#include "data.h" namespace saw { struct schema_hash_combine { static constexpr uint64_t apply(uint64_t seed, uint64_t v){ - return (seed ^ v) * 1099511628211u; - - return seed ^( std::hash<uint64_t>{}(v) + 0x9e3779b9 + (seed<<6) + (seed >> 2)); } }; +template<string_literal lit> +struct schema_hash_literal { + static constexpr uint64_t apply(uint64_t seed){ + constexpr std::string_view view = lit.view(); + for(uint64_t i = 0; i < view.size(); ++i){ + seed = schema_hash_combine::apply(seed, static_cast<uint64_t>(view[i])); + } + return seed; + } +}; + template<typename Schema> struct schema_hash { static_assert(always_false<Schema>, "Not schema_hashable"); }; template<> -struct schema_hash<schema::Primitive<schema::SignedInteger,1>> { - static constexpr uint64_t base_value = 0u; -}; - -template<> -struct schema_hash<schema::Primitive<schema::SignedInteger,2>> { - static constexpr uint64_t base_value = 1u; -}; - -template<> -struct schema_hash<schema::Primitive<schema::SignedInteger,4>> { - static constexpr uint64_t base_value = 2u; -}; - -template<> -struct schema_hash<schema::Primitive<schema::SignedInteger,8>> { - static constexpr uint64_t base_value = 3u; -}; - -template<> -struct schema_hash<schema::Primitive<schema::UnsignedInteger,1>> { - static constexpr uint64_t base_value = 4u; -}; - -template<> -struct schema_hash<schema::Primitive<schema::UnsignedInteger,2>> { - static constexpr uint64_t base_value = 5u; -}; - -template<> -struct schema_hash<schema::Primitive<schema::UnsignedInteger,4>> { - static constexpr uint64_t base_value = 6u; -}; - -template<> -struct schema_hash<schema::Primitive<schema::UnsignedInteger,8>> { - static constexpr uint64_t base_value = 7u; -}; - -template<> -struct schema_hash<schema::Primitive<schema::FloatingPoint,4>> { - static constexpr uint64_t base_value = 8u; -}; - -template<> -struct schema_hash<schema::Primitive<schema::FloatingPoint,8>> { - static constexpr uint64_t base_value = 9u; -}; - -template<typename... T> -struct schema_hash<schema::Tuple<T...>> { - static constexpr uint64_t base_value = 10u; -}; - -template<typename... T, string_literal Literal> -struct schema_hash<schema::Struct<schema::Member<T,Literal>...>> { - static constexpr uint64_t base_value = 11u; -}; - -template<typename... T, string_literal Literal> -struct schema_hash<schema::Union<schema::Member<T,Literal>...>> { - static constexpr uint64_t base_value = 12u; -}; - -template<typename T, size_t Dim> -struct schema_hash<schema::Array<T,Dim>> { - static constexpr uint64_t base_value = 13u; -}; - -template<> struct schema_hash<schema::String> { - static constexpr uint64_t base_value = 14u; -}; + using Schema = schema::String; -template<typename T, typename N> -struct schema_hash<schema::Wrapper<T,N>> { - static constexpr uint64_t base_value = 15u; -}; - -template<typename T, size_t... Dims> -struct schema_hash<schema::FixedArray<T,Dims...>> { - static constexpr uint64_t base_value = 16u; + static constexpr uint64_t apply(uint64_t seed, const data<Schema>& val){ + seed = schema_hash_literal<Schema::name>::apply(seed); + for(size_t i = 0; i < val.size(); ++i){ + seed = schema_hash_combine::apply(seed, static_cast<uint64_t>(val.at(i))); + } + return seed; + } }; } diff --git a/modules/codec/tests/schema.cpp b/modules/codec/tests/schema.cpp new file mode 100644 index 0000000..e1c2f82 --- /dev/null +++ b/modules/codec/tests/schema.cpp @@ -0,0 +1,13 @@ +#include <forstio/test/suite.h> +#include "../c++/schema.h" +#include "../c++/schema_hash.h" + +namespace { +SAW_TEST("Schema String Hash"){ + using namespace saw; + data<schema::String> str{"foo"}; + uint64_t hash = schema_hash<schema::String>::apply(0, str); + + SAW_EXPECT( hash == 0, std::string{"Hash is "} + std::to_string(hash) +", but should be 0."); +} +} |