Spicy
unit.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <vector>
6 
7 #include <hilti/ast/builder/expression.h>
8 #include <hilti/ast/operator.h>
9 #include <hilti/ast/operators/common.h>
10 #include <hilti/ast/types/bytes.h>
11 #include <hilti/ast/types/computed.h>
12 #include <hilti/ast/types/integer.h>
13 #include <hilti/ast/types/stream.h>
14 
15 #include <spicy/ast/types/unit.h>
16 
17 namespace spicy::operator_ {
18 
19 BEGIN_METHOD(unit, Offset)
20  auto signature() const {
21  return hilti::operator_::Signature{.self = hilti::type::constant(spicy::type::Unit(type::Wildcard())),
22  .result = hilti::type::UnsignedInteger(64),
23  .id = "offset",
24  .args = {},
25  .doc = R"(
26 Returns the offset of the current location in the input stream relative to the
27 unit's start. If executed from inside a field hook, the offset will represent
28 the first byte that the field has been parsed from. If this method is called
29 before the unit's parsing has begun, it will throw a runtime exception. Once
30 parsing has started, the offset will remain available for the unit's entire
31 life time.
32 
33 Usage of this method requires the unit to be declared with the ``%random-access``
34 property.
35 )"};
36  }
37 END_METHOD
38 
39 BEGIN_METHOD(unit, Position)
40  auto signature() const {
41  return hilti::operator_::Signature{.self = hilti::type::constant(spicy::type::Unit(type::Wildcard())),
43  .id = "position",
44  .args = {},
45  .doc = R"(
46 Returns an iterator to the current position in the unit's input stream. If
47 executed from inside a field hook, the position will represent the first byte
48 that the field has been parsed from. If this method is called before the unit's
49 parsing has begun, it will throw a runtime exception.
50 
51 Usage of this method requires the unit to be declared with the ``%random-access``
52 property.
53 )"};
54  }
55 END_METHOD
56 
57 
58 BEGIN_METHOD(unit, Input)
59  auto signature() const {
60  return hilti::operator_::Signature{.self = hilti::type::constant(spicy::type::Unit(type::Wildcard())),
62  .id = "input",
63  .args = {},
64  .doc = R"(
65 Returns an iterator referring to the input location where the current unit has
66 begun parsing. If this method is called before the units parsing has begun, it
67 will throw a runtime exception. Once available, the input position will remain
68 accessible for the unit's entire life time.
69 
70 Usage of this method requires the unit to be declared with the ``%random-access``
71 property.
72 )"};
73  }
74 END_METHOD
75 
76 BEGIN_METHOD(unit, SetInput)
77  auto signature() const {
78  return hilti::operator_::Signature{.self = hilti::type::constant(spicy::type::Unit(type::Wildcard())),
79  .result = hilti::type::Void(),
80  .id = "set_input",
81  .args = {{.id = "i",
82  .type = type::constant(hilti::type::stream::Iterator())}},
83  .doc = R"(
84 Moves the current parsing position to *i*. The iterator *i* must be into the
85 input of the current unit, or the method will throw a runtime execption.
86 
87 Usage of this method requires the unit to be declared with the ``%random-access``
88 property.
89 )"};
90  }
91 END_METHOD
92 
93 BEGIN_METHOD(unit, Find)
94  auto signature() const {
95  return hilti::operator_::Signature{.self = hilti::type::constant(spicy::type::Unit(type::Wildcard())),
97  .id = "find",
98  .args =
99  {
100  {.id = "needle", .type = type::constant(hilti::type::Bytes())},
101  {.id = "dir",
102  .type = type::constant(hilti::type::Enum(type::Wildcard())),
103  .optional = true},
104  {.id = "start",
105  .type = type::constant(hilti::type::stream::Iterator()),
106  .optional = true},
107 
108  },
109  .doc = R"(
110 Searches a *needle* pattern inside the input region defined by where the unit
111 began parsing and its current parsing position. If executed from inside a field
112 hook, the current parasing position will represent the *first* byte that the
113 field has been parsed from. By default, the search will start at the beginning
114 of that region and scan forward. If the direction is
115 ``spicy::Direcction::Backward``, the search will start at the end of the region
116 and scan backward. In either case, a starting position can also be explicitly
117 given, but must lie inside the same region.
118 
119 Usage of this method requires the unit to be declared with the ``%random-access``
120 property.
121 )"};
122  }
123 END_METHOD
124 
125 BEGIN_METHOD(unit, ConnectFilter)
126  auto signature() const {
127  return hilti::operator_::Signature{.self = hilti::type::constant(spicy::type::Unit(type::Wildcard())),
128  .result = hilti::type::Void(),
129  .id = "connect_filter",
130  .args = {{.id = "filter",
132  spicy::type::Unit(type::Wildcard()))}},
133  .doc = R"(
134 Connects a separate filter unit to transform the unit's input transparently
135 before parsing. The filter unit will see the original input, and this unit will
136 receive everything the filter passes on through ``forward()``.
137 
138 Filters can be connected only before a unit's parsing begins. The latest
139 possible point is from inside the target unit's ``%init`` hook.
140 )"};
141  }
142 END_METHOD
143 
144 BEGIN_METHOD(unit, Forward)
145  auto signature() const {
146  return hilti::operator_::Signature{.self = hilti::type::constant(spicy::type::Unit(type::Wildcard())),
147  .result = hilti::type::Void(),
148  .id = "forward",
149  .args = {{.id = "data", .type = hilti::type::Bytes()}},
150  .doc = R"(
151 If the unit is connected as a filter to another one, this method forwards
152 transformed input over to that other one to parse. If the unit is not connected,
153 this method will silently discard the data.
154 )"};
155  }
156 END_METHOD
157 
158 BEGIN_METHOD(unit, ForwardEod)
159  auto signature() const {
160  return hilti::operator_::Signature{.self = hilti::type::constant(spicy::type::Unit(type::Wildcard())),
161  .result = hilti::type::Void(),
162  .id = "forward_eod",
163  .args = {},
164  .doc = R"(
165 If the unit is connected as a filter to another one, this method signals that
166 other one that end of its input has been reached. If the unit is not connected,
167 this method will not do anything.
168 )"};
169  }
170 END_METHOD
171 
172 BEGIN_METHOD(unit, Backtrack)
173  auto signature() const {
174  return hilti::operator_::Signature{.self = hilti::type::constant(spicy::type::Unit(type::Wildcard())),
175  .result = hilti::type::Void(),
176  .id = "backtrack",
177  .args = {},
178  .doc = R"(
179 Aborts parsing at the current position and returns back to the most recent
180 ``&try`` attribute. Turns into a parse error if there's no ``&try`` in scope.
181 )"};
182  }
183 END_METHOD
184 
185 static inline auto contextResult(bool is_const) {
186  return [=](const std::vector<Expression>& /* orig_ops */,
187  const std::vector<Expression>& resolved_ops) -> std::optional<Type> {
188  if ( resolved_ops.empty() )
189  return type::DocOnly("<context>&");
190 
191  return type::Computed(hilti::builder::member(hilti::builder::id("self"), "__context"));
192  };
193 }
194 
195 BEGIN_METHOD(unit, ContextConst)
196  auto signature() const {
197  return hilti::operator_::Signature{.self = hilti::type::constant(spicy::type::Unit(type::Wildcard())),
198  .result = contextResult(true),
199  .id = "context",
200  .args = {},
201  .doc = R"(
202 Returns a reference to the ``%context`` instance associated with the unit.
203 )"};
204  }
205 END_METHOD
206 
207 BEGIN_METHOD(unit, ContextNonConst)
208  auto signature() const {
209  return hilti::operator_::Signature{.self = spicy::type::Unit(type::Wildcard()),
210  .result = contextResult(false),
211  .id = "context",
212  .args = {},
213  .doc = R"(
214 Returns a reference to the ``%context`` instance associated with the unit.
215 )"};
216  }
217 END_METHOD
218 
219 } // namespace spicy::operator_
Definition: void.h:13
Definition: unit.h:51
Definition: optional.h:13
Definition: reference.h:16
Type self
Definition: operator.h:225
Definition: integer.h:53
Definition: bytes.h:38
Definition: stream.h:16
Definition: bitfield.h:18
Definition: enum.h:40
Definition: operator.h:224