bytes.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#ifndef CRUCIBLE_PARSING_BYTES_HPP #define CRUCIBLE_PARSING_BYTES_HPP #include "crucible/parsing/errors.inl" #include "crucible/core/none.hpp" #include <concepts> #include <cstddef> #include <cstdint> #include <span> #include <vector> namespace crucible::parsing::bytes { template<typename T> concept UnsignedIntegerType = std::same_as<T, std::uint8_t> || std::same_as<T, std::uint16_t> || std::same_as<T, std::uint32_t> || std::same_as<T, std::uint64_t>; enum class Endianness { Le, Be }; class State final { public: explicit State(std::span<std::byte const> const input); State(std::span<std::byte const> const input, std::size_t const offset); [[nodiscard]] auto has_remaining_input() const -> bool; [[nodiscard]] auto get_remaining_input() const -> std::span<std::byte const>; [[nodiscard]] auto advance(std::size_t const count) const -> State; private: std::span<std::byte const> my_input {}; std::size_t my_offset { 0 }; }; class Exact final { public: using StateType = State; using ValueType = std::vector<std::byte>; using ResultType = errors::ParsingResult<StateType, ValueType>; Exact(std::vector<std::byte> const &bytes); [[nodiscard]] auto operator()(StateType const &initial_state) const -> ResultType; private: std::vector<std::byte> my_bytes {}; }; class Take final { public: using StateType = State; using ValueType = std::vector<std::byte>; using ResultType = errors::ParsingResult<StateType, ValueType>; Take(std::size_t const count); [[nodiscard]] auto operator()(StateType const &initial_state) const -> ResultType; private: std::size_t my_count { 0 }; }; template<UnsignedIntegerType T, Endianness E> struct UnsignedInteger final { using StateType = State; using ValueType = T; using ResultType = errors::ParsingResult<StateType, ValueType>; [[nodiscard]] auto operator()(StateType const &initial_state) const -> ResultType; }; using U8Le = UnsignedInteger<std::uint8_t, Endianness::Le>; using U16Le = UnsignedInteger<std::uint16_t, Endianness::Le>; using U32Le = UnsignedInteger<std::uint32_t, Endianness::Le>; using U64Le = UnsignedInteger<std::uint64_t, Endianness::Le>; using U8Be = UnsignedInteger<std::uint8_t, Endianness::Be>; using U16Be = UnsignedInteger<std::uint16_t, Endianness::Be>; using U32Be = UnsignedInteger<std::uint32_t, Endianness::Be>; using U64Be = UnsignedInteger<std::uint64_t, Endianness::Be>; auto make_exact(std::vector<std::byte> const &sequence) -> Exact; auto make_take(std::size_t const count) -> Take; auto make_u8_le() -> U8Le; auto make_u16_le() -> U16Le; auto make_u32_le() -> U32Le; auto make_u64_le() -> U64Le; auto make_u8_be() -> U8Be; auto make_u16_be() -> U16Be; auto make_u32_be() -> U32Be; auto make_u64_be() -> U64Be; } #endif // CRUCIBLE_PARSING_BYTES_HPP