Echo Writes Code

bytes.cpp

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
#include "crucible/parsing/bytes.inl"

#include <algorithm>
#include <climits>
#include <sstream>

namespace crucible::parsing::bytes {
  State::State(std::span<std::byte const> const input) :
    my_input { input } {
  }

  State::State(std::span<std::byte const> const input, std::size_t const offset) :
    my_input { input },
    my_offset { offset } {
  }

  auto State::has_remaining_input() const -> bool {
    return my_offset < my_input.size();
  }

  auto State::get_remaining_input() const -> std::span<std::byte const> {
    return my_input.subspan(my_offset);
  }

  auto State::advance(std::size_t const count) const -> State {
    return State { my_input, my_offset + count };
  }

  Exact::Exact(std::vector<std::byte> const &bytes) :
    my_bytes { bytes } {
  }

  auto Exact::operator()(StateType const &initial_state) const -> ResultType {
    auto const &remaining_bytes { initial_state.get_remaining_input() };

    if (remaining_bytes.size() < my_bytes.size()) {
      return errors::make_reject(initial_state, errors::InsufficientInput { my_bytes.size() });
    }

    auto const sequence_begin { my_bytes.begin() };
    auto const sequence_end { my_bytes.end() };
    auto const input_begin { remaining_bytes.begin() };
    bool const is_equal { std::equal(sequence_begin, sequence_end, input_begin) };

    if (is_equal) {
      auto const next_state { initial_state.advance(my_bytes.size()) };
      return errors::make_accept(next_state, my_bytes);
    } else {
      return errors::make_reject(initial_state, errors::ExpectedExactBytes { my_bytes });
    }
  }

  Take::Take(std::size_t const count) :
    my_count { count } {
  }

  auto Take::operator()(StateType const &initial_state) const -> ResultType {
    auto const &remaining_bytes { initial_state.get_remaining_input() };

    if (remaining_bytes.size() < my_count) {
      return errors::make_reject(initial_state, errors::InsufficientInput { my_count });
    }

    auto const result { remaining_bytes.first(my_count) };
    auto const next_state { initial_state.advance(my_count) };

    return errors::make_accept(next_state, std::vector<std::byte>(result.begin(), result.end()));
  }

  auto make_exact(std::vector<std::byte> const &sequence) -> Exact {
    return { sequence };
  }

  auto make_take(std::size_t const count) -> Take {
    return { count };
  }

  auto make_u8_le() -> UnsignedInteger<std::uint8_t, Endianness::Le> {
    return {};
  }

  auto make_u16_le() -> UnsignedInteger<std::uint16_t, Endianness::Le> {
    return {};
  }

  auto make_u32_le() -> UnsignedInteger<std::uint32_t, Endianness::Le> {
    return {};
  }

  auto make_u64_le() -> UnsignedInteger<std::uint64_t, Endianness::Le> {
    return {};
  }

  auto make_u8_be() -> UnsignedInteger<std::uint8_t, Endianness::Be> {
    return {};
  }

  auto make_u16_be() -> UnsignedInteger<std::uint16_t, Endianness::Be> {
    return {};
  }

  auto make_u32_be() -> UnsignedInteger<std::uint32_t, Endianness::Be> {
    return {};
  }

  auto make_u64_be() -> UnsignedInteger<std::uint64_t, Endianness::Be> {
    return {};
  }
}