1*993b0882SAndroid Build Coastguard Worker /*
2*993b0882SAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*993b0882SAndroid Build Coastguard Worker *
4*993b0882SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*993b0882SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*993b0882SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*993b0882SAndroid Build Coastguard Worker *
8*993b0882SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*993b0882SAndroid Build Coastguard Worker *
10*993b0882SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*993b0882SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*993b0882SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*993b0882SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*993b0882SAndroid Build Coastguard Worker * limitations under the License.
15*993b0882SAndroid Build Coastguard Worker */
16*993b0882SAndroid Build Coastguard Worker
17*993b0882SAndroid Build Coastguard Worker #ifndef LIBTEXTCLASSIFIER_UTILS_LUA_UTILS_H_
18*993b0882SAndroid Build Coastguard Worker #define LIBTEXTCLASSIFIER_UTILS_LUA_UTILS_H_
19*993b0882SAndroid Build Coastguard Worker
20*993b0882SAndroid Build Coastguard Worker #include <vector>
21*993b0882SAndroid Build Coastguard Worker
22*993b0882SAndroid Build Coastguard Worker #include "actions/types.h"
23*993b0882SAndroid Build Coastguard Worker #include "annotator/types.h"
24*993b0882SAndroid Build Coastguard Worker #include "utils/flatbuffers/mutable.h"
25*993b0882SAndroid Build Coastguard Worker #include "utils/strings/stringpiece.h"
26*993b0882SAndroid Build Coastguard Worker #include "utils/variant.h"
27*993b0882SAndroid Build Coastguard Worker #include "flatbuffers/reflection_generated.h"
28*993b0882SAndroid Build Coastguard Worker
29*993b0882SAndroid Build Coastguard Worker #ifdef __cplusplus
30*993b0882SAndroid Build Coastguard Worker extern "C" {
31*993b0882SAndroid Build Coastguard Worker #endif
32*993b0882SAndroid Build Coastguard Worker #include "lauxlib.h"
33*993b0882SAndroid Build Coastguard Worker #include "lua.h"
34*993b0882SAndroid Build Coastguard Worker #include "lualib.h"
35*993b0882SAndroid Build Coastguard Worker #ifdef __cplusplus
36*993b0882SAndroid Build Coastguard Worker }
37*993b0882SAndroid Build Coastguard Worker #endif
38*993b0882SAndroid Build Coastguard Worker
39*993b0882SAndroid Build Coastguard Worker namespace libtextclassifier3 {
40*993b0882SAndroid Build Coastguard Worker
41*993b0882SAndroid Build Coastguard Worker static constexpr const char kLengthKey[] = "__len";
42*993b0882SAndroid Build Coastguard Worker static constexpr const char kPairsKey[] = "__pairs";
43*993b0882SAndroid Build Coastguard Worker static constexpr const char kIndexKey[] = "__index";
44*993b0882SAndroid Build Coastguard Worker static constexpr const char kGcKey[] = "__gc";
45*993b0882SAndroid Build Coastguard Worker static constexpr const char kNextKey[] = "__next";
46*993b0882SAndroid Build Coastguard Worker
47*993b0882SAndroid Build Coastguard Worker static constexpr const int kIndexStackTop = -1;
48*993b0882SAndroid Build Coastguard Worker
49*993b0882SAndroid Build Coastguard Worker // Casts to the lua user data type.
50*993b0882SAndroid Build Coastguard Worker template <typename T>
AsUserData(const T * value)51*993b0882SAndroid Build Coastguard Worker void* AsUserData(const T* value) {
52*993b0882SAndroid Build Coastguard Worker return static_cast<void*>(const_cast<T*>(value));
53*993b0882SAndroid Build Coastguard Worker }
54*993b0882SAndroid Build Coastguard Worker template <typename T>
AsUserData(const T value)55*993b0882SAndroid Build Coastguard Worker void* AsUserData(const T value) {
56*993b0882SAndroid Build Coastguard Worker return reinterpret_cast<void*>(value);
57*993b0882SAndroid Build Coastguard Worker }
58*993b0882SAndroid Build Coastguard Worker
59*993b0882SAndroid Build Coastguard Worker // Retrieves up-values.
60*993b0882SAndroid Build Coastguard Worker template <typename T>
FromUpValue(const int index,lua_State * state)61*993b0882SAndroid Build Coastguard Worker T FromUpValue(const int index, lua_State* state) {
62*993b0882SAndroid Build Coastguard Worker return static_cast<T>(lua_touserdata(state, lua_upvalueindex(index)));
63*993b0882SAndroid Build Coastguard Worker }
64*993b0882SAndroid Build Coastguard Worker
65*993b0882SAndroid Build Coastguard Worker class LuaEnvironment {
66*993b0882SAndroid Build Coastguard Worker public:
67*993b0882SAndroid Build Coastguard Worker virtual ~LuaEnvironment();
68*993b0882SAndroid Build Coastguard Worker explicit LuaEnvironment();
69*993b0882SAndroid Build Coastguard Worker
70*993b0882SAndroid Build Coastguard Worker // Compile a lua snippet into binary bytecode.
71*993b0882SAndroid Build Coastguard Worker // NOTE: The compiled bytecode might not be compatible across Lua versions
72*993b0882SAndroid Build Coastguard Worker // and platforms.
73*993b0882SAndroid Build Coastguard Worker bool Compile(StringPiece snippet, std::string* bytecode) const;
74*993b0882SAndroid Build Coastguard Worker
75*993b0882SAndroid Build Coastguard Worker // Loads default libraries.
76*993b0882SAndroid Build Coastguard Worker void LoadDefaultLibraries();
77*993b0882SAndroid Build Coastguard Worker
78*993b0882SAndroid Build Coastguard Worker // Provides a callback to Lua.
79*993b0882SAndroid Build Coastguard Worker template <typename T>
PushFunction(int (T::* handler)())80*993b0882SAndroid Build Coastguard Worker void PushFunction(int (T::*handler)()) {
81*993b0882SAndroid Build Coastguard Worker PushFunction(std::bind(handler, static_cast<T*>(this)));
82*993b0882SAndroid Build Coastguard Worker }
83*993b0882SAndroid Build Coastguard Worker
84*993b0882SAndroid Build Coastguard Worker template <typename F>
PushFunction(const F & func)85*993b0882SAndroid Build Coastguard Worker void PushFunction(const F& func) const {
86*993b0882SAndroid Build Coastguard Worker // Copy closure to the lua stack.
87*993b0882SAndroid Build Coastguard Worker new (lua_newuserdata(state_, sizeof(func))) F(func);
88*993b0882SAndroid Build Coastguard Worker
89*993b0882SAndroid Build Coastguard Worker // Register garbage collection callback.
90*993b0882SAndroid Build Coastguard Worker lua_newtable(state_);
91*993b0882SAndroid Build Coastguard Worker lua_pushcfunction(state_, &ReleaseFunction<F>);
92*993b0882SAndroid Build Coastguard Worker lua_setfield(state_, -2, kGcKey);
93*993b0882SAndroid Build Coastguard Worker lua_setmetatable(state_, -2);
94*993b0882SAndroid Build Coastguard Worker
95*993b0882SAndroid Build Coastguard Worker // Push dispatch.
96*993b0882SAndroid Build Coastguard Worker lua_pushcclosure(state_, &CallFunction<F>, 1);
97*993b0882SAndroid Build Coastguard Worker }
98*993b0882SAndroid Build Coastguard Worker
99*993b0882SAndroid Build Coastguard Worker // Sets up a named table that calls back whenever a member is accessed.
100*993b0882SAndroid Build Coastguard Worker // This allows to lazily provide required information to the script.
101*993b0882SAndroid Build Coastguard Worker template <typename T>
PushLazyObject(int (T::* handler)())102*993b0882SAndroid Build Coastguard Worker void PushLazyObject(int (T::*handler)()) {
103*993b0882SAndroid Build Coastguard Worker PushLazyObject(std::bind(handler, static_cast<T*>(this)));
104*993b0882SAndroid Build Coastguard Worker }
105*993b0882SAndroid Build Coastguard Worker
106*993b0882SAndroid Build Coastguard Worker template <typename F>
PushLazyObject(const F & func)107*993b0882SAndroid Build Coastguard Worker void PushLazyObject(const F& func) const {
108*993b0882SAndroid Build Coastguard Worker lua_newtable(state_);
109*993b0882SAndroid Build Coastguard Worker lua_newtable(state_);
110*993b0882SAndroid Build Coastguard Worker PushFunction(func);
111*993b0882SAndroid Build Coastguard Worker lua_setfield(state_, -2, kIndexKey);
112*993b0882SAndroid Build Coastguard Worker lua_setmetatable(state_, -2);
113*993b0882SAndroid Build Coastguard Worker }
114*993b0882SAndroid Build Coastguard Worker
Push(const int64 value)115*993b0882SAndroid Build Coastguard Worker void Push(const int64 value) const { lua_pushinteger(state_, value); }
Push(const uint64 value)116*993b0882SAndroid Build Coastguard Worker void Push(const uint64 value) const { lua_pushinteger(state_, value); }
Push(const int32 value)117*993b0882SAndroid Build Coastguard Worker void Push(const int32 value) const { lua_pushinteger(state_, value); }
Push(const uint32 value)118*993b0882SAndroid Build Coastguard Worker void Push(const uint32 value) const { lua_pushinteger(state_, value); }
Push(const int16 value)119*993b0882SAndroid Build Coastguard Worker void Push(const int16 value) const { lua_pushinteger(state_, value); }
Push(const uint16 value)120*993b0882SAndroid Build Coastguard Worker void Push(const uint16 value) const { lua_pushinteger(state_, value); }
Push(const int8 value)121*993b0882SAndroid Build Coastguard Worker void Push(const int8 value) const { lua_pushinteger(state_, value); }
Push(const uint8 value)122*993b0882SAndroid Build Coastguard Worker void Push(const uint8 value) const { lua_pushinteger(state_, value); }
Push(const float value)123*993b0882SAndroid Build Coastguard Worker void Push(const float value) const { lua_pushnumber(state_, value); }
Push(const double value)124*993b0882SAndroid Build Coastguard Worker void Push(const double value) const { lua_pushnumber(state_, value); }
Push(const bool value)125*993b0882SAndroid Build Coastguard Worker void Push(const bool value) const { lua_pushboolean(state_, value); }
Push(const StringPiece value)126*993b0882SAndroid Build Coastguard Worker void Push(const StringPiece value) const { PushString(value); }
Push(const flatbuffers::String * value)127*993b0882SAndroid Build Coastguard Worker void Push(const flatbuffers::String* value) const {
128*993b0882SAndroid Build Coastguard Worker if (value == nullptr) {
129*993b0882SAndroid Build Coastguard Worker PushString("");
130*993b0882SAndroid Build Coastguard Worker } else {
131*993b0882SAndroid Build Coastguard Worker PushString(StringPiece(value->c_str(), value->size()));
132*993b0882SAndroid Build Coastguard Worker }
133*993b0882SAndroid Build Coastguard Worker }
134*993b0882SAndroid Build Coastguard Worker
135*993b0882SAndroid Build Coastguard Worker template <typename T>
136*993b0882SAndroid Build Coastguard Worker T Read(const int index = -1) const;
137*993b0882SAndroid Build Coastguard Worker
138*993b0882SAndroid Build Coastguard Worker template <>
139*993b0882SAndroid Build Coastguard Worker int64 Read<int64>(const int index) const {
140*993b0882SAndroid Build Coastguard Worker return static_cast<int64>(lua_tointeger(state_, /*idx=*/index));
141*993b0882SAndroid Build Coastguard Worker }
142*993b0882SAndroid Build Coastguard Worker
143*993b0882SAndroid Build Coastguard Worker template <>
144*993b0882SAndroid Build Coastguard Worker uint64 Read<uint64>(const int index) const {
145*993b0882SAndroid Build Coastguard Worker return static_cast<uint64>(lua_tointeger(state_, /*idx=*/index));
146*993b0882SAndroid Build Coastguard Worker }
147*993b0882SAndroid Build Coastguard Worker
148*993b0882SAndroid Build Coastguard Worker template <>
149*993b0882SAndroid Build Coastguard Worker int32 Read<int32>(const int index) const {
150*993b0882SAndroid Build Coastguard Worker return static_cast<int32>(lua_tointeger(state_, /*idx=*/index));
151*993b0882SAndroid Build Coastguard Worker }
152*993b0882SAndroid Build Coastguard Worker
153*993b0882SAndroid Build Coastguard Worker template <>
154*993b0882SAndroid Build Coastguard Worker uint32 Read<uint32>(const int index) const {
155*993b0882SAndroid Build Coastguard Worker return static_cast<uint32>(lua_tointeger(state_, /*idx=*/index));
156*993b0882SAndroid Build Coastguard Worker }
157*993b0882SAndroid Build Coastguard Worker
158*993b0882SAndroid Build Coastguard Worker template <>
159*993b0882SAndroid Build Coastguard Worker int16 Read<int16>(const int index) const {
160*993b0882SAndroid Build Coastguard Worker return static_cast<int16>(lua_tointeger(state_, /*idx=*/index));
161*993b0882SAndroid Build Coastguard Worker }
162*993b0882SAndroid Build Coastguard Worker
163*993b0882SAndroid Build Coastguard Worker template <>
164*993b0882SAndroid Build Coastguard Worker uint16 Read<uint16>(const int index) const {
165*993b0882SAndroid Build Coastguard Worker return static_cast<uint16>(lua_tointeger(state_, /*idx=*/index));
166*993b0882SAndroid Build Coastguard Worker }
167*993b0882SAndroid Build Coastguard Worker
168*993b0882SAndroid Build Coastguard Worker template <>
169*993b0882SAndroid Build Coastguard Worker int8 Read<int8>(const int index) const {
170*993b0882SAndroid Build Coastguard Worker return static_cast<int8>(lua_tointeger(state_, /*idx=*/index));
171*993b0882SAndroid Build Coastguard Worker }
172*993b0882SAndroid Build Coastguard Worker
173*993b0882SAndroid Build Coastguard Worker template <>
174*993b0882SAndroid Build Coastguard Worker uint8 Read<uint8>(const int index) const {
175*993b0882SAndroid Build Coastguard Worker return static_cast<uint8>(lua_tointeger(state_, /*idx=*/index));
176*993b0882SAndroid Build Coastguard Worker }
177*993b0882SAndroid Build Coastguard Worker
178*993b0882SAndroid Build Coastguard Worker template <>
179*993b0882SAndroid Build Coastguard Worker float Read<float>(const int index) const {
180*993b0882SAndroid Build Coastguard Worker return static_cast<float>(lua_tonumber(state_, /*idx=*/index));
181*993b0882SAndroid Build Coastguard Worker }
182*993b0882SAndroid Build Coastguard Worker
183*993b0882SAndroid Build Coastguard Worker template <>
184*993b0882SAndroid Build Coastguard Worker double Read<double>(const int index) const {
185*993b0882SAndroid Build Coastguard Worker return static_cast<double>(lua_tonumber(state_, /*idx=*/index));
186*993b0882SAndroid Build Coastguard Worker }
187*993b0882SAndroid Build Coastguard Worker
188*993b0882SAndroid Build Coastguard Worker template <>
189*993b0882SAndroid Build Coastguard Worker bool Read<bool>(const int index) const {
190*993b0882SAndroid Build Coastguard Worker return lua_toboolean(state_, /*idx=*/index);
191*993b0882SAndroid Build Coastguard Worker }
192*993b0882SAndroid Build Coastguard Worker
193*993b0882SAndroid Build Coastguard Worker template <>
194*993b0882SAndroid Build Coastguard Worker StringPiece Read<StringPiece>(const int index) const {
195*993b0882SAndroid Build Coastguard Worker return ReadString(index);
196*993b0882SAndroid Build Coastguard Worker }
197*993b0882SAndroid Build Coastguard Worker
198*993b0882SAndroid Build Coastguard Worker template <>
199*993b0882SAndroid Build Coastguard Worker std::string Read<std::string>(const int index) const {
200*993b0882SAndroid Build Coastguard Worker return ReadString(index).ToString();
201*993b0882SAndroid Build Coastguard Worker }
202*993b0882SAndroid Build Coastguard Worker
203*993b0882SAndroid Build Coastguard Worker // Reads a string from the stack.
204*993b0882SAndroid Build Coastguard Worker StringPiece ReadString(int index) const;
205*993b0882SAndroid Build Coastguard Worker
206*993b0882SAndroid Build Coastguard Worker // Pushes a string to the stack.
207*993b0882SAndroid Build Coastguard Worker void PushString(const StringPiece str) const;
208*993b0882SAndroid Build Coastguard Worker
209*993b0882SAndroid Build Coastguard Worker // Pushes a flatbuffer to the stack.
PushFlatbuffer(const reflection::Schema * schema,const flatbuffers::Table * table)210*993b0882SAndroid Build Coastguard Worker void PushFlatbuffer(const reflection::Schema* schema,
211*993b0882SAndroid Build Coastguard Worker const flatbuffers::Table* table) const {
212*993b0882SAndroid Build Coastguard Worker PushFlatbuffer(schema, schema->root_table(), table);
213*993b0882SAndroid Build Coastguard Worker }
214*993b0882SAndroid Build Coastguard Worker
215*993b0882SAndroid Build Coastguard Worker // Reads a flatbuffer from the stack.
216*993b0882SAndroid Build Coastguard Worker int ReadFlatbuffer(int index, MutableFlatbuffer* buffer) const;
217*993b0882SAndroid Build Coastguard Worker
218*993b0882SAndroid Build Coastguard Worker // Pushes an iterator.
219*993b0882SAndroid Build Coastguard Worker template <typename ItemCallback, typename KeyCallback>
PushIterator(const int length,const ItemCallback & item_callback,const KeyCallback & key_callback)220*993b0882SAndroid Build Coastguard Worker void PushIterator(const int length, const ItemCallback& item_callback,
221*993b0882SAndroid Build Coastguard Worker const KeyCallback& key_callback) const {
222*993b0882SAndroid Build Coastguard Worker lua_newtable(state_);
223*993b0882SAndroid Build Coastguard Worker CreateIteratorMetatable(length, item_callback);
224*993b0882SAndroid Build Coastguard Worker PushFunction([this, length, item_callback, key_callback]() {
225*993b0882SAndroid Build Coastguard Worker return Iterator::Dispatch(this, length, item_callback, key_callback);
226*993b0882SAndroid Build Coastguard Worker });
227*993b0882SAndroid Build Coastguard Worker lua_setfield(state_, -2, kIndexKey);
228*993b0882SAndroid Build Coastguard Worker lua_setmetatable(state_, -2);
229*993b0882SAndroid Build Coastguard Worker }
230*993b0882SAndroid Build Coastguard Worker
231*993b0882SAndroid Build Coastguard Worker template <typename ItemCallback>
PushIterator(const int length,const ItemCallback & item_callback)232*993b0882SAndroid Build Coastguard Worker void PushIterator(const int length, const ItemCallback& item_callback) const {
233*993b0882SAndroid Build Coastguard Worker lua_newtable(state_);
234*993b0882SAndroid Build Coastguard Worker CreateIteratorMetatable(length, item_callback);
235*993b0882SAndroid Build Coastguard Worker PushFunction([this, length, item_callback]() {
236*993b0882SAndroid Build Coastguard Worker return Iterator::Dispatch(this, length, item_callback);
237*993b0882SAndroid Build Coastguard Worker });
238*993b0882SAndroid Build Coastguard Worker lua_setfield(state_, -2, kIndexKey);
239*993b0882SAndroid Build Coastguard Worker lua_setmetatable(state_, -2);
240*993b0882SAndroid Build Coastguard Worker }
241*993b0882SAndroid Build Coastguard Worker
242*993b0882SAndroid Build Coastguard Worker template <typename ItemCallback>
CreateIteratorMetatable(const int length,const ItemCallback & item_callback)243*993b0882SAndroid Build Coastguard Worker void CreateIteratorMetatable(const int length,
244*993b0882SAndroid Build Coastguard Worker const ItemCallback& item_callback) const {
245*993b0882SAndroid Build Coastguard Worker lua_newtable(state_);
246*993b0882SAndroid Build Coastguard Worker PushFunction([this, length]() { return Iterator::Length(this, length); });
247*993b0882SAndroid Build Coastguard Worker lua_setfield(state_, -2, kLengthKey);
248*993b0882SAndroid Build Coastguard Worker PushFunction([this, length, item_callback]() {
249*993b0882SAndroid Build Coastguard Worker return Iterator::IterItems(this, length, item_callback);
250*993b0882SAndroid Build Coastguard Worker });
251*993b0882SAndroid Build Coastguard Worker lua_setfield(state_, -2, kPairsKey);
252*993b0882SAndroid Build Coastguard Worker PushFunction([this, length, item_callback]() {
253*993b0882SAndroid Build Coastguard Worker return Iterator::Next(this, length, item_callback);
254*993b0882SAndroid Build Coastguard Worker });
255*993b0882SAndroid Build Coastguard Worker lua_setfield(state_, -2, kNextKey);
256*993b0882SAndroid Build Coastguard Worker }
257*993b0882SAndroid Build Coastguard Worker
258*993b0882SAndroid Build Coastguard Worker template <typename T>
PushVectorIterator(const std::vector<T> * items)259*993b0882SAndroid Build Coastguard Worker void PushVectorIterator(const std::vector<T>* items) const {
260*993b0882SAndroid Build Coastguard Worker PushIterator(items ? items->size() : 0, [this, items](const int64 pos) {
261*993b0882SAndroid Build Coastguard Worker this->Push(items->at(pos));
262*993b0882SAndroid Build Coastguard Worker return 1;
263*993b0882SAndroid Build Coastguard Worker });
264*993b0882SAndroid Build Coastguard Worker }
265*993b0882SAndroid Build Coastguard Worker
266*993b0882SAndroid Build Coastguard Worker template <typename T>
PushVector(const std::vector<T> & items)267*993b0882SAndroid Build Coastguard Worker void PushVector(const std::vector<T>& items) const {
268*993b0882SAndroid Build Coastguard Worker lua_newtable(state_);
269*993b0882SAndroid Build Coastguard Worker for (int i = 0; i < items.size(); i++) {
270*993b0882SAndroid Build Coastguard Worker // Key: index, 1-based.
271*993b0882SAndroid Build Coastguard Worker Push(i + 1);
272*993b0882SAndroid Build Coastguard Worker
273*993b0882SAndroid Build Coastguard Worker // Value.
274*993b0882SAndroid Build Coastguard Worker Push(items[i]);
275*993b0882SAndroid Build Coastguard Worker lua_settable(state_, /*idx=*/-3);
276*993b0882SAndroid Build Coastguard Worker }
277*993b0882SAndroid Build Coastguard Worker }
278*993b0882SAndroid Build Coastguard Worker
PushEmptyVector()279*993b0882SAndroid Build Coastguard Worker void PushEmptyVector() const { lua_newtable(state_); }
280*993b0882SAndroid Build Coastguard Worker
281*993b0882SAndroid Build Coastguard Worker template <typename T>
282*993b0882SAndroid Build Coastguard Worker std::vector<T> ReadVector(const int index = -1) const {
283*993b0882SAndroid Build Coastguard Worker std::vector<T> result;
284*993b0882SAndroid Build Coastguard Worker if (lua_type(state_, /*idx=*/index) != LUA_TTABLE) {
285*993b0882SAndroid Build Coastguard Worker TC3_LOG(ERROR) << "Expected a table, got: "
286*993b0882SAndroid Build Coastguard Worker << lua_type(state_, /*idx=*/kIndexStackTop);
287*993b0882SAndroid Build Coastguard Worker lua_pop(state_, 1);
288*993b0882SAndroid Build Coastguard Worker return {};
289*993b0882SAndroid Build Coastguard Worker }
290*993b0882SAndroid Build Coastguard Worker lua_pushnil(state_);
291*993b0882SAndroid Build Coastguard Worker while (Next(index - 1)) {
292*993b0882SAndroid Build Coastguard Worker result.push_back(Read<T>(/*index=*/kIndexStackTop));
293*993b0882SAndroid Build Coastguard Worker lua_pop(state_, 1);
294*993b0882SAndroid Build Coastguard Worker }
295*993b0882SAndroid Build Coastguard Worker return result;
296*993b0882SAndroid Build Coastguard Worker }
297*993b0882SAndroid Build Coastguard Worker
298*993b0882SAndroid Build Coastguard Worker // Runs a closure in protected mode.
299*993b0882SAndroid Build Coastguard Worker // `func`: closure to run in protected mode.
300*993b0882SAndroid Build Coastguard Worker // `num_lua_args`: number of arguments from the lua stack to process.
301*993b0882SAndroid Build Coastguard Worker // `num_results`: number of result values pushed on the stack.
302*993b0882SAndroid Build Coastguard Worker template <typename F>
303*993b0882SAndroid Build Coastguard Worker int RunProtected(const F& func, const int num_args = 0,
304*993b0882SAndroid Build Coastguard Worker const int num_results = 0) const {
305*993b0882SAndroid Build Coastguard Worker PushFunction(func);
306*993b0882SAndroid Build Coastguard Worker // Put the closure before the arguments on the stack.
307*993b0882SAndroid Build Coastguard Worker if (num_args > 0) {
308*993b0882SAndroid Build Coastguard Worker lua_insert(state_, -(1 + num_args));
309*993b0882SAndroid Build Coastguard Worker }
310*993b0882SAndroid Build Coastguard Worker return lua_pcall(state_, num_args, num_results, /*errorfunc=*/0);
311*993b0882SAndroid Build Coastguard Worker }
312*993b0882SAndroid Build Coastguard Worker
313*993b0882SAndroid Build Coastguard Worker // Auxiliary methods to handle model results.
314*993b0882SAndroid Build Coastguard Worker // Provides an annotation to lua.
315*993b0882SAndroid Build Coastguard Worker void PushAnnotation(const ClassificationResult& classification,
316*993b0882SAndroid Build Coastguard Worker const reflection::Schema* entity_data_schema) const;
317*993b0882SAndroid Build Coastguard Worker void PushAnnotation(const ClassificationResult& classification,
318*993b0882SAndroid Build Coastguard Worker StringPiece text,
319*993b0882SAndroid Build Coastguard Worker const reflection::Schema* entity_data_schema) const;
320*993b0882SAndroid Build Coastguard Worker void PushAnnotation(const ActionSuggestionAnnotation& annotation,
321*993b0882SAndroid Build Coastguard Worker const reflection::Schema* entity_data_schema) const;
322*993b0882SAndroid Build Coastguard Worker
323*993b0882SAndroid Build Coastguard Worker template <typename Annotation>
PushAnnotations(const std::vector<Annotation> * annotations,const reflection::Schema * entity_data_schema)324*993b0882SAndroid Build Coastguard Worker void PushAnnotations(const std::vector<Annotation>* annotations,
325*993b0882SAndroid Build Coastguard Worker const reflection::Schema* entity_data_schema) const {
326*993b0882SAndroid Build Coastguard Worker PushIterator(
327*993b0882SAndroid Build Coastguard Worker annotations ? annotations->size() : 0,
328*993b0882SAndroid Build Coastguard Worker [this, annotations, entity_data_schema](const int64 index) {
329*993b0882SAndroid Build Coastguard Worker PushAnnotation(annotations->at(index), entity_data_schema);
330*993b0882SAndroid Build Coastguard Worker return 1;
331*993b0882SAndroid Build Coastguard Worker },
332*993b0882SAndroid Build Coastguard Worker [this, annotations, entity_data_schema](StringPiece name) {
333*993b0882SAndroid Build Coastguard Worker if (const Annotation* annotation =
334*993b0882SAndroid Build Coastguard Worker GetAnnotationByName(*annotations, name)) {
335*993b0882SAndroid Build Coastguard Worker PushAnnotation(*annotation, entity_data_schema);
336*993b0882SAndroid Build Coastguard Worker return 1;
337*993b0882SAndroid Build Coastguard Worker } else {
338*993b0882SAndroid Build Coastguard Worker return 0;
339*993b0882SAndroid Build Coastguard Worker }
340*993b0882SAndroid Build Coastguard Worker });
341*993b0882SAndroid Build Coastguard Worker }
342*993b0882SAndroid Build Coastguard Worker
343*993b0882SAndroid Build Coastguard Worker // Pushes a span to the lua stack.
344*993b0882SAndroid Build Coastguard Worker void PushAnnotatedSpan(const AnnotatedSpan& annotated_span,
345*993b0882SAndroid Build Coastguard Worker const reflection::Schema* entity_data_schema) const;
346*993b0882SAndroid Build Coastguard Worker void PushAnnotatedSpans(const std::vector<AnnotatedSpan>* annotated_spans,
347*993b0882SAndroid Build Coastguard Worker const reflection::Schema* entity_data_schema) const;
348*993b0882SAndroid Build Coastguard Worker
349*993b0882SAndroid Build Coastguard Worker // Reads a message text span from lua.
350*993b0882SAndroid Build Coastguard Worker MessageTextSpan ReadSpan() const;
351*993b0882SAndroid Build Coastguard Worker
352*993b0882SAndroid Build Coastguard Worker ActionSuggestionAnnotation ReadAnnotation(
353*993b0882SAndroid Build Coastguard Worker const reflection::Schema* entity_data_schema) const;
354*993b0882SAndroid Build Coastguard Worker int ReadAnnotations(
355*993b0882SAndroid Build Coastguard Worker const reflection::Schema* entity_data_schema,
356*993b0882SAndroid Build Coastguard Worker std::vector<ActionSuggestionAnnotation>* annotations) const;
357*993b0882SAndroid Build Coastguard Worker ClassificationResult ReadClassificationResult(
358*993b0882SAndroid Build Coastguard Worker const reflection::Schema* entity_data_schema) const;
359*993b0882SAndroid Build Coastguard Worker
360*993b0882SAndroid Build Coastguard Worker // Provides an action to lua.
361*993b0882SAndroid Build Coastguard Worker void PushAction(
362*993b0882SAndroid Build Coastguard Worker const ActionSuggestion& action,
363*993b0882SAndroid Build Coastguard Worker const reflection::Schema* actions_entity_data_schema,
364*993b0882SAndroid Build Coastguard Worker const reflection::Schema* annotations_entity_data_schema) const;
365*993b0882SAndroid Build Coastguard Worker
366*993b0882SAndroid Build Coastguard Worker void PushActions(
367*993b0882SAndroid Build Coastguard Worker const std::vector<ActionSuggestion>* actions,
368*993b0882SAndroid Build Coastguard Worker const reflection::Schema* actions_entity_data_schema,
369*993b0882SAndroid Build Coastguard Worker const reflection::Schema* annotations_entity_data_schema) const;
370*993b0882SAndroid Build Coastguard Worker
371*993b0882SAndroid Build Coastguard Worker ActionSuggestion ReadAction(
372*993b0882SAndroid Build Coastguard Worker const reflection::Schema* actions_entity_data_schema,
373*993b0882SAndroid Build Coastguard Worker const reflection::Schema* annotations_entity_data_schema) const;
374*993b0882SAndroid Build Coastguard Worker
375*993b0882SAndroid Build Coastguard Worker int ReadActions(const reflection::Schema* actions_entity_data_schema,
376*993b0882SAndroid Build Coastguard Worker const reflection::Schema* annotations_entity_data_schema,
377*993b0882SAndroid Build Coastguard Worker std::vector<ActionSuggestion>* actions) const;
378*993b0882SAndroid Build Coastguard Worker
379*993b0882SAndroid Build Coastguard Worker // Conversation message iterator.
380*993b0882SAndroid Build Coastguard Worker void PushConversation(
381*993b0882SAndroid Build Coastguard Worker const std::vector<ConversationMessage>* conversation,
382*993b0882SAndroid Build Coastguard Worker const reflection::Schema* annotations_entity_data_schema) const;
383*993b0882SAndroid Build Coastguard Worker
state()384*993b0882SAndroid Build Coastguard Worker lua_State* state() const { return state_; }
385*993b0882SAndroid Build Coastguard Worker
386*993b0882SAndroid Build Coastguard Worker protected:
387*993b0882SAndroid Build Coastguard Worker // Wrapper for handling iteration over containers.
388*993b0882SAndroid Build Coastguard Worker class Iterator {
389*993b0882SAndroid Build Coastguard Worker public:
390*993b0882SAndroid Build Coastguard Worker // Starts a new key-value pair iterator.
391*993b0882SAndroid Build Coastguard Worker template <typename ItemCallback>
IterItems(const LuaEnvironment * env,const int length,const ItemCallback & callback)392*993b0882SAndroid Build Coastguard Worker static int IterItems(const LuaEnvironment* env, const int length,
393*993b0882SAndroid Build Coastguard Worker const ItemCallback& callback) {
394*993b0882SAndroid Build Coastguard Worker env->PushFunction([env, callback, length, pos = 0]() mutable {
395*993b0882SAndroid Build Coastguard Worker if (pos >= length) {
396*993b0882SAndroid Build Coastguard Worker lua_pushnil(env->state());
397*993b0882SAndroid Build Coastguard Worker return 1;
398*993b0882SAndroid Build Coastguard Worker }
399*993b0882SAndroid Build Coastguard Worker
400*993b0882SAndroid Build Coastguard Worker // Push key.
401*993b0882SAndroid Build Coastguard Worker lua_pushinteger(env->state(), pos + 1);
402*993b0882SAndroid Build Coastguard Worker
403*993b0882SAndroid Build Coastguard Worker // Push item.
404*993b0882SAndroid Build Coastguard Worker return 1 + callback(pos++);
405*993b0882SAndroid Build Coastguard Worker });
406*993b0882SAndroid Build Coastguard Worker return 1; // Num. results.
407*993b0882SAndroid Build Coastguard Worker }
408*993b0882SAndroid Build Coastguard Worker
409*993b0882SAndroid Build Coastguard Worker // Gets the next element.
410*993b0882SAndroid Build Coastguard Worker template <typename ItemCallback>
Next(const LuaEnvironment * env,const int length,const ItemCallback & item_callback)411*993b0882SAndroid Build Coastguard Worker static int Next(const LuaEnvironment* env, const int length,
412*993b0882SAndroid Build Coastguard Worker const ItemCallback& item_callback) {
413*993b0882SAndroid Build Coastguard Worker int64 pos = lua_isnil(env->state(), /*idx=*/kIndexStackTop)
414*993b0882SAndroid Build Coastguard Worker ? 0
415*993b0882SAndroid Build Coastguard Worker : env->Read<int64>(/*index=*/kIndexStackTop);
416*993b0882SAndroid Build Coastguard Worker if (pos < length) {
417*993b0882SAndroid Build Coastguard Worker // Push next key.
418*993b0882SAndroid Build Coastguard Worker lua_pushinteger(env->state(), pos + 1);
419*993b0882SAndroid Build Coastguard Worker
420*993b0882SAndroid Build Coastguard Worker // Push item.
421*993b0882SAndroid Build Coastguard Worker return 1 + item_callback(pos);
422*993b0882SAndroid Build Coastguard Worker } else {
423*993b0882SAndroid Build Coastguard Worker lua_pushnil(env->state());
424*993b0882SAndroid Build Coastguard Worker return 1;
425*993b0882SAndroid Build Coastguard Worker }
426*993b0882SAndroid Build Coastguard Worker }
427*993b0882SAndroid Build Coastguard Worker
428*993b0882SAndroid Build Coastguard Worker // Returns the length of the container the iterator processes.
Length(const LuaEnvironment * env,const int length)429*993b0882SAndroid Build Coastguard Worker static int Length(const LuaEnvironment* env, const int length) {
430*993b0882SAndroid Build Coastguard Worker lua_pushinteger(env->state(), length);
431*993b0882SAndroid Build Coastguard Worker return 1; // Num. results.
432*993b0882SAndroid Build Coastguard Worker }
433*993b0882SAndroid Build Coastguard Worker
434*993b0882SAndroid Build Coastguard Worker // Handles item queries to the iterator.
435*993b0882SAndroid Build Coastguard Worker // Elements of the container can either be queried by name or index.
436*993b0882SAndroid Build Coastguard Worker // Dispatch will check how an element is accessed and
437*993b0882SAndroid Build Coastguard Worker // calls `key_callback` for access by name and `item_callback` for access by
438*993b0882SAndroid Build Coastguard Worker // index.
439*993b0882SAndroid Build Coastguard Worker template <typename ItemCallback, typename KeyCallback>
Dispatch(const LuaEnvironment * env,const int length,const ItemCallback & item_callback,const KeyCallback & key_callback)440*993b0882SAndroid Build Coastguard Worker static int Dispatch(const LuaEnvironment* env, const int length,
441*993b0882SAndroid Build Coastguard Worker const ItemCallback& item_callback,
442*993b0882SAndroid Build Coastguard Worker const KeyCallback& key_callback) {
443*993b0882SAndroid Build Coastguard Worker switch (lua_type(env->state(), kIndexStackTop)) {
444*993b0882SAndroid Build Coastguard Worker case LUA_TNUMBER: {
445*993b0882SAndroid Build Coastguard Worker // Lua is one based, so adjust the index here.
446*993b0882SAndroid Build Coastguard Worker const int64 index = env->Read<int64>(/*index=*/kIndexStackTop) - 1;
447*993b0882SAndroid Build Coastguard Worker if (index < 0 || index >= length) {
448*993b0882SAndroid Build Coastguard Worker TC3_LOG(ERROR) << "Invalid index: " << index;
449*993b0882SAndroid Build Coastguard Worker lua_error(env->state());
450*993b0882SAndroid Build Coastguard Worker return 0;
451*993b0882SAndroid Build Coastguard Worker }
452*993b0882SAndroid Build Coastguard Worker return item_callback(index);
453*993b0882SAndroid Build Coastguard Worker }
454*993b0882SAndroid Build Coastguard Worker case LUA_TSTRING: {
455*993b0882SAndroid Build Coastguard Worker return key_callback(env->ReadString(kIndexStackTop));
456*993b0882SAndroid Build Coastguard Worker }
457*993b0882SAndroid Build Coastguard Worker default:
458*993b0882SAndroid Build Coastguard Worker TC3_LOG(ERROR) << "Unexpected access type: "
459*993b0882SAndroid Build Coastguard Worker << lua_type(env->state(), kIndexStackTop);
460*993b0882SAndroid Build Coastguard Worker lua_error(env->state());
461*993b0882SAndroid Build Coastguard Worker return 0;
462*993b0882SAndroid Build Coastguard Worker }
463*993b0882SAndroid Build Coastguard Worker }
464*993b0882SAndroid Build Coastguard Worker
465*993b0882SAndroid Build Coastguard Worker template <typename ItemCallback>
Dispatch(const LuaEnvironment * env,const int length,const ItemCallback & item_callback)466*993b0882SAndroid Build Coastguard Worker static int Dispatch(const LuaEnvironment* env, const int length,
467*993b0882SAndroid Build Coastguard Worker const ItemCallback& item_callback) {
468*993b0882SAndroid Build Coastguard Worker switch (lua_type(env->state(), kIndexStackTop)) {
469*993b0882SAndroid Build Coastguard Worker case LUA_TNUMBER: {
470*993b0882SAndroid Build Coastguard Worker // Lua is one based, so adjust the index here.
471*993b0882SAndroid Build Coastguard Worker const int64 index = env->Read<int64>(/*index=*/kIndexStackTop) - 1;
472*993b0882SAndroid Build Coastguard Worker if (index < 0 || index >= length) {
473*993b0882SAndroid Build Coastguard Worker TC3_LOG(ERROR) << "Invalid index: " << index;
474*993b0882SAndroid Build Coastguard Worker lua_error(env->state());
475*993b0882SAndroid Build Coastguard Worker return 0;
476*993b0882SAndroid Build Coastguard Worker }
477*993b0882SAndroid Build Coastguard Worker return item_callback(index);
478*993b0882SAndroid Build Coastguard Worker }
479*993b0882SAndroid Build Coastguard Worker default:
480*993b0882SAndroid Build Coastguard Worker TC3_LOG(ERROR) << "Unexpected access type: "
481*993b0882SAndroid Build Coastguard Worker << lua_type(env->state(), kIndexStackTop);
482*993b0882SAndroid Build Coastguard Worker lua_error(env->state());
483*993b0882SAndroid Build Coastguard Worker return 0;
484*993b0882SAndroid Build Coastguard Worker }
485*993b0882SAndroid Build Coastguard Worker }
486*993b0882SAndroid Build Coastguard Worker };
487*993b0882SAndroid Build Coastguard Worker
488*993b0882SAndroid Build Coastguard Worker // Calls the deconstructor from a previously pushed function.
489*993b0882SAndroid Build Coastguard Worker template <typename T>
ReleaseFunction(lua_State * state)490*993b0882SAndroid Build Coastguard Worker static int ReleaseFunction(lua_State* state) {
491*993b0882SAndroid Build Coastguard Worker static_cast<T*>(lua_touserdata(state, 1))->~T();
492*993b0882SAndroid Build Coastguard Worker return 0;
493*993b0882SAndroid Build Coastguard Worker }
494*993b0882SAndroid Build Coastguard Worker
495*993b0882SAndroid Build Coastguard Worker template <typename T>
CallFunction(lua_State * state)496*993b0882SAndroid Build Coastguard Worker static int CallFunction(lua_State* state) {
497*993b0882SAndroid Build Coastguard Worker return (*static_cast<T*>(lua_touserdata(state, lua_upvalueindex(1))))();
498*993b0882SAndroid Build Coastguard Worker }
499*993b0882SAndroid Build Coastguard Worker
500*993b0882SAndroid Build Coastguard Worker // Auxiliary methods to expose (reflective) flatbuffer based data to Lua.
501*993b0882SAndroid Build Coastguard Worker void PushFlatbuffer(const reflection::Schema* schema,
502*993b0882SAndroid Build Coastguard Worker const reflection::Object* type,
503*993b0882SAndroid Build Coastguard Worker const flatbuffers::Table* table) const;
504*993b0882SAndroid Build Coastguard Worker int GetField(const reflection::Schema* schema, const reflection::Object* type,
505*993b0882SAndroid Build Coastguard Worker const flatbuffers::Table* table) const;
506*993b0882SAndroid Build Coastguard Worker
507*993b0882SAndroid Build Coastguard Worker // Reads a repeated field from lua.
508*993b0882SAndroid Build Coastguard Worker template <typename T>
ReadRepeatedField(const int index,RepeatedField * result)509*993b0882SAndroid Build Coastguard Worker void ReadRepeatedField(const int index, RepeatedField* result) const {
510*993b0882SAndroid Build Coastguard Worker for (const T& element : ReadVector<T>(index)) {
511*993b0882SAndroid Build Coastguard Worker result->Add(element);
512*993b0882SAndroid Build Coastguard Worker }
513*993b0882SAndroid Build Coastguard Worker }
514*993b0882SAndroid Build Coastguard Worker
515*993b0882SAndroid Build Coastguard Worker template <>
516*993b0882SAndroid Build Coastguard Worker void ReadRepeatedField<MutableFlatbuffer>(const int index,
517*993b0882SAndroid Build Coastguard Worker RepeatedField* result) const {
518*993b0882SAndroid Build Coastguard Worker lua_pushnil(state_);
519*993b0882SAndroid Build Coastguard Worker while (Next(index - 1)) {
520*993b0882SAndroid Build Coastguard Worker ReadFlatbuffer(index, result->Add());
521*993b0882SAndroid Build Coastguard Worker lua_pop(state_, 1);
522*993b0882SAndroid Build Coastguard Worker }
523*993b0882SAndroid Build Coastguard Worker }
524*993b0882SAndroid Build Coastguard Worker
525*993b0882SAndroid Build Coastguard Worker // Pushes a repeated field to the lua stack.
526*993b0882SAndroid Build Coastguard Worker template <typename T>
PushRepeatedField(const flatbuffers::Vector<T> * items)527*993b0882SAndroid Build Coastguard Worker void PushRepeatedField(const flatbuffers::Vector<T>* items) const {
528*993b0882SAndroid Build Coastguard Worker PushIterator(items ? items->size() : 0, [this, items](const int64 pos) {
529*993b0882SAndroid Build Coastguard Worker Push(items->Get(pos));
530*993b0882SAndroid Build Coastguard Worker return 1; // Num. results.
531*993b0882SAndroid Build Coastguard Worker });
532*993b0882SAndroid Build Coastguard Worker }
533*993b0882SAndroid Build Coastguard Worker
PushRepeatedFlatbufferField(const reflection::Schema * schema,const reflection::Object * type,const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::Table>> * items)534*993b0882SAndroid Build Coastguard Worker void PushRepeatedFlatbufferField(
535*993b0882SAndroid Build Coastguard Worker const reflection::Schema* schema, const reflection::Object* type,
536*993b0882SAndroid Build Coastguard Worker const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::Table>>* items)
537*993b0882SAndroid Build Coastguard Worker const {
538*993b0882SAndroid Build Coastguard Worker PushIterator(items ? items->size() : 0,
539*993b0882SAndroid Build Coastguard Worker [this, schema, type, items](const int64 pos) {
540*993b0882SAndroid Build Coastguard Worker PushFlatbuffer(schema, type, items->Get(pos));
541*993b0882SAndroid Build Coastguard Worker return 1; // Num. results.
542*993b0882SAndroid Build Coastguard Worker });
543*993b0882SAndroid Build Coastguard Worker }
544*993b0882SAndroid Build Coastguard Worker
545*993b0882SAndroid Build Coastguard Worker // Overloads Lua next function to use __next key on the metatable.
546*993b0882SAndroid Build Coastguard Worker // This allows us to treat lua objects and lazy objects provided by our
547*993b0882SAndroid Build Coastguard Worker // callbacks uniformly.
Next(int index)548*993b0882SAndroid Build Coastguard Worker int Next(int index) const {
549*993b0882SAndroid Build Coastguard Worker // Check whether the (meta)table of this object has an associated "__next"
550*993b0882SAndroid Build Coastguard Worker // entry. This means, we registered our own callback. So we explicitly call
551*993b0882SAndroid Build Coastguard Worker // that.
552*993b0882SAndroid Build Coastguard Worker if (luaL_getmetafield(state_, index, kNextKey)) {
553*993b0882SAndroid Build Coastguard Worker // Callback is now on top of the stack, so adjust relative indices by 1.
554*993b0882SAndroid Build Coastguard Worker if (index < 0) {
555*993b0882SAndroid Build Coastguard Worker index--;
556*993b0882SAndroid Build Coastguard Worker }
557*993b0882SAndroid Build Coastguard Worker
558*993b0882SAndroid Build Coastguard Worker // Copy the reference to the table.
559*993b0882SAndroid Build Coastguard Worker lua_pushvalue(state_, index);
560*993b0882SAndroid Build Coastguard Worker
561*993b0882SAndroid Build Coastguard Worker // Move the key to top to have it as second argument for the callback.
562*993b0882SAndroid Build Coastguard Worker // Copy the key to the top.
563*993b0882SAndroid Build Coastguard Worker lua_pushvalue(state_, -3);
564*993b0882SAndroid Build Coastguard Worker
565*993b0882SAndroid Build Coastguard Worker // Remove the copy of the key.
566*993b0882SAndroid Build Coastguard Worker lua_remove(state_, -4);
567*993b0882SAndroid Build Coastguard Worker
568*993b0882SAndroid Build Coastguard Worker // Call the callback with (key and table as arguments).
569*993b0882SAndroid Build Coastguard Worker lua_pcall(state_, /*nargs=*/2 /* table, key */,
570*993b0882SAndroid Build Coastguard Worker /*nresults=*/2 /* key, item */, 0);
571*993b0882SAndroid Build Coastguard Worker
572*993b0882SAndroid Build Coastguard Worker // Next returned nil, it's the end.
573*993b0882SAndroid Build Coastguard Worker if (lua_isnil(state_, kIndexStackTop)) {
574*993b0882SAndroid Build Coastguard Worker // Remove nil value.
575*993b0882SAndroid Build Coastguard Worker // Results will be padded to `nresults` specified above, so we need
576*993b0882SAndroid Build Coastguard Worker // to remove two elements here.
577*993b0882SAndroid Build Coastguard Worker lua_pop(state_, 2);
578*993b0882SAndroid Build Coastguard Worker return 0;
579*993b0882SAndroid Build Coastguard Worker }
580*993b0882SAndroid Build Coastguard Worker
581*993b0882SAndroid Build Coastguard Worker return 2; // Num. results.
582*993b0882SAndroid Build Coastguard Worker } else if (lua_istable(state_, index)) {
583*993b0882SAndroid Build Coastguard Worker return lua_next(state_, index);
584*993b0882SAndroid Build Coastguard Worker }
585*993b0882SAndroid Build Coastguard Worker
586*993b0882SAndroid Build Coastguard Worker // Remove the key.
587*993b0882SAndroid Build Coastguard Worker lua_pop(state_, 1);
588*993b0882SAndroid Build Coastguard Worker return 0;
589*993b0882SAndroid Build Coastguard Worker }
590*993b0882SAndroid Build Coastguard Worker
GetAnnotationByName(const std::vector<ClassificationResult> & annotations,StringPiece name)591*993b0882SAndroid Build Coastguard Worker static const ClassificationResult* GetAnnotationByName(
592*993b0882SAndroid Build Coastguard Worker const std::vector<ClassificationResult>& annotations, StringPiece name) {
593*993b0882SAndroid Build Coastguard Worker // Lookup annotation by collection.
594*993b0882SAndroid Build Coastguard Worker for (const ClassificationResult& annotation : annotations) {
595*993b0882SAndroid Build Coastguard Worker if (name.Equals(annotation.collection)) {
596*993b0882SAndroid Build Coastguard Worker return &annotation;
597*993b0882SAndroid Build Coastguard Worker }
598*993b0882SAndroid Build Coastguard Worker }
599*993b0882SAndroid Build Coastguard Worker TC3_LOG(ERROR) << "No annotation with collection: " << name << " found.";
600*993b0882SAndroid Build Coastguard Worker return nullptr;
601*993b0882SAndroid Build Coastguard Worker }
602*993b0882SAndroid Build Coastguard Worker
GetAnnotationByName(const std::vector<ActionSuggestionAnnotation> & annotations,StringPiece name)603*993b0882SAndroid Build Coastguard Worker static const ActionSuggestionAnnotation* GetAnnotationByName(
604*993b0882SAndroid Build Coastguard Worker const std::vector<ActionSuggestionAnnotation>& annotations,
605*993b0882SAndroid Build Coastguard Worker StringPiece name) {
606*993b0882SAndroid Build Coastguard Worker // Lookup annotation by name.
607*993b0882SAndroid Build Coastguard Worker for (const ActionSuggestionAnnotation& annotation : annotations) {
608*993b0882SAndroid Build Coastguard Worker if (name.Equals(annotation.name)) {
609*993b0882SAndroid Build Coastguard Worker return &annotation;
610*993b0882SAndroid Build Coastguard Worker }
611*993b0882SAndroid Build Coastguard Worker }
612*993b0882SAndroid Build Coastguard Worker TC3_LOG(ERROR) << "No annotation with name: " << name << " found.";
613*993b0882SAndroid Build Coastguard Worker return nullptr;
614*993b0882SAndroid Build Coastguard Worker }
615*993b0882SAndroid Build Coastguard Worker
616*993b0882SAndroid Build Coastguard Worker lua_State* state_;
617*993b0882SAndroid Build Coastguard Worker }; // namespace libtextclassifier3
618*993b0882SAndroid Build Coastguard Worker
619*993b0882SAndroid Build Coastguard Worker bool Compile(StringPiece snippet, std::string* bytecode);
620*993b0882SAndroid Build Coastguard Worker
621*993b0882SAndroid Build Coastguard Worker } // namespace libtextclassifier3
622*993b0882SAndroid Build Coastguard Worker
623*993b0882SAndroid Build Coastguard Worker #endif // LIBTEXTCLASSIFIER_UTILS_LUA_UTILS_H_
624