xref: /aosp_15_r20/external/libtextclassifier/native/utils/lua-utils.cc (revision 993b0882672172b81d12fad7a7ac0c3e5c824a12)
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 #include "utils/lua-utils.h"
18*993b0882SAndroid Build Coastguard Worker 
19*993b0882SAndroid Build Coastguard Worker namespace libtextclassifier3 {
20*993b0882SAndroid Build Coastguard Worker namespace {
21*993b0882SAndroid Build Coastguard Worker static constexpr luaL_Reg defaultlibs[] = {{"_G", luaopen_base},
22*993b0882SAndroid Build Coastguard Worker                                            {LUA_TABLIBNAME, luaopen_table},
23*993b0882SAndroid Build Coastguard Worker                                            {LUA_STRLIBNAME, luaopen_string},
24*993b0882SAndroid Build Coastguard Worker                                            {LUA_MATHLIBNAME, luaopen_math},
25*993b0882SAndroid Build Coastguard Worker                                            {nullptr, nullptr}};
26*993b0882SAndroid Build Coastguard Worker 
27*993b0882SAndroid Build Coastguard Worker static constexpr const char kTextKey[] = "text";
28*993b0882SAndroid Build Coastguard Worker static constexpr const char kTimeUsecKey[] = "parsed_time_ms_utc";
29*993b0882SAndroid Build Coastguard Worker static constexpr const char kGranularityKey[] = "granularity";
30*993b0882SAndroid Build Coastguard Worker static constexpr const char kCollectionKey[] = "collection";
31*993b0882SAndroid Build Coastguard Worker static constexpr const char kNameKey[] = "name";
32*993b0882SAndroid Build Coastguard Worker static constexpr const char kScoreKey[] = "score";
33*993b0882SAndroid Build Coastguard Worker static constexpr const char kPriorityScoreKey[] = "priority_score";
34*993b0882SAndroid Build Coastguard Worker static constexpr const char kTypeKey[] = "type";
35*993b0882SAndroid Build Coastguard Worker static constexpr const char kResponseTextKey[] = "response_text";
36*993b0882SAndroid Build Coastguard Worker static constexpr const char kAnnotationKey[] = "annotation";
37*993b0882SAndroid Build Coastguard Worker static constexpr const char kSpanKey[] = "span";
38*993b0882SAndroid Build Coastguard Worker static constexpr const char kMessageKey[] = "message";
39*993b0882SAndroid Build Coastguard Worker static constexpr const char kBeginKey[] = "begin";
40*993b0882SAndroid Build Coastguard Worker static constexpr const char kEndKey[] = "end";
41*993b0882SAndroid Build Coastguard Worker static constexpr const char kClassificationKey[] = "classification";
42*993b0882SAndroid Build Coastguard Worker static constexpr const char kSerializedEntity[] = "serialized_entity";
43*993b0882SAndroid Build Coastguard Worker static constexpr const char kEntityKey[] = "entity";
44*993b0882SAndroid Build Coastguard Worker 
45*993b0882SAndroid Build Coastguard Worker // Implementation of a lua_Writer that appends the data to a string.
LuaStringWriter(lua_State * state,const void * data,size_t size,void * result)46*993b0882SAndroid Build Coastguard Worker int LuaStringWriter(lua_State* state, const void* data, size_t size,
47*993b0882SAndroid Build Coastguard Worker                     void* result) {
48*993b0882SAndroid Build Coastguard Worker   std::string* const result_string = static_cast<std::string*>(result);
49*993b0882SAndroid Build Coastguard Worker   result_string->insert(result_string->size(), static_cast<const char*>(data),
50*993b0882SAndroid Build Coastguard Worker                         size);
51*993b0882SAndroid Build Coastguard Worker   return LUA_OK;
52*993b0882SAndroid Build Coastguard Worker }
53*993b0882SAndroid Build Coastguard Worker 
54*993b0882SAndroid Build Coastguard Worker }  // namespace
55*993b0882SAndroid Build Coastguard Worker 
LuaEnvironment()56*993b0882SAndroid Build Coastguard Worker LuaEnvironment::LuaEnvironment() { state_ = luaL_newstate(); }
57*993b0882SAndroid Build Coastguard Worker 
~LuaEnvironment()58*993b0882SAndroid Build Coastguard Worker LuaEnvironment::~LuaEnvironment() {
59*993b0882SAndroid Build Coastguard Worker   if (state_ != nullptr) {
60*993b0882SAndroid Build Coastguard Worker     lua_close(state_);
61*993b0882SAndroid Build Coastguard Worker   }
62*993b0882SAndroid Build Coastguard Worker }
63*993b0882SAndroid Build Coastguard Worker 
PushFlatbuffer(const reflection::Schema * schema,const reflection::Object * type,const flatbuffers::Table * table) const64*993b0882SAndroid Build Coastguard Worker void LuaEnvironment::PushFlatbuffer(const reflection::Schema* schema,
65*993b0882SAndroid Build Coastguard Worker                                     const reflection::Object* type,
66*993b0882SAndroid Build Coastguard Worker                                     const flatbuffers::Table* table) const {
67*993b0882SAndroid Build Coastguard Worker   PushLazyObject(
68*993b0882SAndroid Build Coastguard Worker       std::bind(&LuaEnvironment::GetField, this, schema, type, table));
69*993b0882SAndroid Build Coastguard Worker }
70*993b0882SAndroid Build Coastguard Worker 
GetField(const reflection::Schema * schema,const reflection::Object * type,const flatbuffers::Table * table) const71*993b0882SAndroid Build Coastguard Worker int LuaEnvironment::GetField(const reflection::Schema* schema,
72*993b0882SAndroid Build Coastguard Worker                              const reflection::Object* type,
73*993b0882SAndroid Build Coastguard Worker                              const flatbuffers::Table* table) const {
74*993b0882SAndroid Build Coastguard Worker   const char* field_name = lua_tostring(state_, /*idx=*/kIndexStackTop);
75*993b0882SAndroid Build Coastguard Worker   const reflection::Field* field = type->fields()->LookupByKey(field_name);
76*993b0882SAndroid Build Coastguard Worker   if (field == nullptr) {
77*993b0882SAndroid Build Coastguard Worker     lua_error(state_);
78*993b0882SAndroid Build Coastguard Worker     return 0;
79*993b0882SAndroid Build Coastguard Worker   }
80*993b0882SAndroid Build Coastguard Worker   // Provide primitive fields directly.
81*993b0882SAndroid Build Coastguard Worker   const reflection::BaseType field_type = field->type()->base_type();
82*993b0882SAndroid Build Coastguard Worker   switch (field_type) {
83*993b0882SAndroid Build Coastguard Worker     case reflection::Bool:
84*993b0882SAndroid Build Coastguard Worker       Push(table->GetField<bool>(field->offset(), field->default_integer()));
85*993b0882SAndroid Build Coastguard Worker       break;
86*993b0882SAndroid Build Coastguard Worker     case reflection::UByte:
87*993b0882SAndroid Build Coastguard Worker       Push(table->GetField<uint8>(field->offset(), field->default_integer()));
88*993b0882SAndroid Build Coastguard Worker       break;
89*993b0882SAndroid Build Coastguard Worker     case reflection::Byte:
90*993b0882SAndroid Build Coastguard Worker       Push(table->GetField<int8>(field->offset(), field->default_integer()));
91*993b0882SAndroid Build Coastguard Worker       break;
92*993b0882SAndroid Build Coastguard Worker     case reflection::Int:
93*993b0882SAndroid Build Coastguard Worker       Push(table->GetField<int32>(field->offset(), field->default_integer()));
94*993b0882SAndroid Build Coastguard Worker       break;
95*993b0882SAndroid Build Coastguard Worker     case reflection::UInt:
96*993b0882SAndroid Build Coastguard Worker       Push(table->GetField<uint32>(field->offset(), field->default_integer()));
97*993b0882SAndroid Build Coastguard Worker       break;
98*993b0882SAndroid Build Coastguard Worker     case reflection::Long:
99*993b0882SAndroid Build Coastguard Worker       Push(table->GetField<int64>(field->offset(), field->default_integer()));
100*993b0882SAndroid Build Coastguard Worker       break;
101*993b0882SAndroid Build Coastguard Worker     case reflection::ULong:
102*993b0882SAndroid Build Coastguard Worker       Push(table->GetField<uint64>(field->offset(), field->default_integer()));
103*993b0882SAndroid Build Coastguard Worker       break;
104*993b0882SAndroid Build Coastguard Worker     case reflection::Float:
105*993b0882SAndroid Build Coastguard Worker       Push(table->GetField<float>(field->offset(), field->default_real()));
106*993b0882SAndroid Build Coastguard Worker       break;
107*993b0882SAndroid Build Coastguard Worker     case reflection::Double:
108*993b0882SAndroid Build Coastguard Worker       Push(table->GetField<double>(field->offset(), field->default_real()));
109*993b0882SAndroid Build Coastguard Worker       break;
110*993b0882SAndroid Build Coastguard Worker     case reflection::String: {
111*993b0882SAndroid Build Coastguard Worker       Push(table->GetPointer<const flatbuffers::String*>(field->offset()));
112*993b0882SAndroid Build Coastguard Worker       break;
113*993b0882SAndroid Build Coastguard Worker     }
114*993b0882SAndroid Build Coastguard Worker     case reflection::Obj: {
115*993b0882SAndroid Build Coastguard Worker       const flatbuffers::Table* field_table =
116*993b0882SAndroid Build Coastguard Worker           table->GetPointer<const flatbuffers::Table*>(field->offset());
117*993b0882SAndroid Build Coastguard Worker       if (field_table == nullptr) {
118*993b0882SAndroid Build Coastguard Worker         // Field was not set in entity data.
119*993b0882SAndroid Build Coastguard Worker         return 0;
120*993b0882SAndroid Build Coastguard Worker       }
121*993b0882SAndroid Build Coastguard Worker       const reflection::Object* field_type =
122*993b0882SAndroid Build Coastguard Worker           schema->objects()->Get(field->type()->index());
123*993b0882SAndroid Build Coastguard Worker       PushFlatbuffer(schema, field_type, field_table);
124*993b0882SAndroid Build Coastguard Worker       break;
125*993b0882SAndroid Build Coastguard Worker     }
126*993b0882SAndroid Build Coastguard Worker     case reflection::Vector: {
127*993b0882SAndroid Build Coastguard Worker       const flatbuffers::Vector<flatbuffers::Offset<void>>* field_vector =
128*993b0882SAndroid Build Coastguard Worker           table->GetPointer<
129*993b0882SAndroid Build Coastguard Worker               const flatbuffers::Vector<flatbuffers::Offset<void>>*>(
130*993b0882SAndroid Build Coastguard Worker               field->offset());
131*993b0882SAndroid Build Coastguard Worker       if (field_vector == nullptr) {
132*993b0882SAndroid Build Coastguard Worker         // Repeated field was not set in flatbuffer.
133*993b0882SAndroid Build Coastguard Worker         PushEmptyVector();
134*993b0882SAndroid Build Coastguard Worker         break;
135*993b0882SAndroid Build Coastguard Worker       }
136*993b0882SAndroid Build Coastguard Worker       switch (field->type()->element()) {
137*993b0882SAndroid Build Coastguard Worker         case reflection::Bool:
138*993b0882SAndroid Build Coastguard Worker           PushRepeatedField(table->GetPointer<const flatbuffers::Vector<bool>*>(
139*993b0882SAndroid Build Coastguard Worker               field->offset()));
140*993b0882SAndroid Build Coastguard Worker           break;
141*993b0882SAndroid Build Coastguard Worker         case reflection::UByte:
142*993b0882SAndroid Build Coastguard Worker           PushRepeatedField(
143*993b0882SAndroid Build Coastguard Worker               table->GetPointer<const flatbuffers::Vector<uint8>*>(
144*993b0882SAndroid Build Coastguard Worker                   field->offset()));
145*993b0882SAndroid Build Coastguard Worker           break;
146*993b0882SAndroid Build Coastguard Worker         case reflection::Byte:
147*993b0882SAndroid Build Coastguard Worker           PushRepeatedField(table->GetPointer<const flatbuffers::Vector<int8>*>(
148*993b0882SAndroid Build Coastguard Worker               field->offset()));
149*993b0882SAndroid Build Coastguard Worker           break;
150*993b0882SAndroid Build Coastguard Worker         case reflection::Int:
151*993b0882SAndroid Build Coastguard Worker           PushRepeatedField(
152*993b0882SAndroid Build Coastguard Worker               table->GetPointer<const flatbuffers::Vector<int32>*>(
153*993b0882SAndroid Build Coastguard Worker                   field->offset()));
154*993b0882SAndroid Build Coastguard Worker           break;
155*993b0882SAndroid Build Coastguard Worker         case reflection::UInt:
156*993b0882SAndroid Build Coastguard Worker           PushRepeatedField(
157*993b0882SAndroid Build Coastguard Worker               table->GetPointer<const flatbuffers::Vector<uint32>*>(
158*993b0882SAndroid Build Coastguard Worker                   field->offset()));
159*993b0882SAndroid Build Coastguard Worker           break;
160*993b0882SAndroid Build Coastguard Worker         case reflection::Long:
161*993b0882SAndroid Build Coastguard Worker           PushRepeatedField(
162*993b0882SAndroid Build Coastguard Worker               table->GetPointer<const flatbuffers::Vector<int64>*>(
163*993b0882SAndroid Build Coastguard Worker                   field->offset()));
164*993b0882SAndroid Build Coastguard Worker           break;
165*993b0882SAndroid Build Coastguard Worker         case reflection::ULong:
166*993b0882SAndroid Build Coastguard Worker           PushRepeatedField(
167*993b0882SAndroid Build Coastguard Worker               table->GetPointer<const flatbuffers::Vector<uint64>*>(
168*993b0882SAndroid Build Coastguard Worker                   field->offset()));
169*993b0882SAndroid Build Coastguard Worker           break;
170*993b0882SAndroid Build Coastguard Worker         case reflection::Float:
171*993b0882SAndroid Build Coastguard Worker           PushRepeatedField(
172*993b0882SAndroid Build Coastguard Worker               table->GetPointer<const flatbuffers::Vector<float>*>(
173*993b0882SAndroid Build Coastguard Worker                   field->offset()));
174*993b0882SAndroid Build Coastguard Worker           break;
175*993b0882SAndroid Build Coastguard Worker         case reflection::Double:
176*993b0882SAndroid Build Coastguard Worker           PushRepeatedField(
177*993b0882SAndroid Build Coastguard Worker               table->GetPointer<const flatbuffers::Vector<double>*>(
178*993b0882SAndroid Build Coastguard Worker                   field->offset()));
179*993b0882SAndroid Build Coastguard Worker           break;
180*993b0882SAndroid Build Coastguard Worker         case reflection::String:
181*993b0882SAndroid Build Coastguard Worker           PushRepeatedField(
182*993b0882SAndroid Build Coastguard Worker               table->GetPointer<const flatbuffers::Vector<
183*993b0882SAndroid Build Coastguard Worker                   flatbuffers::Offset<flatbuffers::String>>*>(field->offset()));
184*993b0882SAndroid Build Coastguard Worker           break;
185*993b0882SAndroid Build Coastguard Worker         case reflection::Obj:
186*993b0882SAndroid Build Coastguard Worker           PushRepeatedFlatbufferField(
187*993b0882SAndroid Build Coastguard Worker               schema, schema->objects()->Get(field->type()->index()),
188*993b0882SAndroid Build Coastguard Worker               table->GetPointer<const flatbuffers::Vector<
189*993b0882SAndroid Build Coastguard Worker                   flatbuffers::Offset<flatbuffers::Table>>*>(field->offset()));
190*993b0882SAndroid Build Coastguard Worker           break;
191*993b0882SAndroid Build Coastguard Worker         default:
192*993b0882SAndroid Build Coastguard Worker           TC3_LOG(ERROR) << "Unsupported repeated type: "
193*993b0882SAndroid Build Coastguard Worker                          << field->type()->element();
194*993b0882SAndroid Build Coastguard Worker           lua_error(state_);
195*993b0882SAndroid Build Coastguard Worker           return 0;
196*993b0882SAndroid Build Coastguard Worker       }
197*993b0882SAndroid Build Coastguard Worker       break;
198*993b0882SAndroid Build Coastguard Worker     }
199*993b0882SAndroid Build Coastguard Worker     default:
200*993b0882SAndroid Build Coastguard Worker       TC3_LOG(ERROR) << "Unsupported type: " << field_type;
201*993b0882SAndroid Build Coastguard Worker       lua_error(state_);
202*993b0882SAndroid Build Coastguard Worker       return 0;
203*993b0882SAndroid Build Coastguard Worker   }
204*993b0882SAndroid Build Coastguard Worker   return 1;
205*993b0882SAndroid Build Coastguard Worker }
206*993b0882SAndroid Build Coastguard Worker 
ReadFlatbuffer(const int index,MutableFlatbuffer * buffer) const207*993b0882SAndroid Build Coastguard Worker int LuaEnvironment::ReadFlatbuffer(const int index,
208*993b0882SAndroid Build Coastguard Worker                                    MutableFlatbuffer* buffer) const {
209*993b0882SAndroid Build Coastguard Worker   if (buffer == nullptr) {
210*993b0882SAndroid Build Coastguard Worker     TC3_LOG(ERROR) << "Called ReadFlatbuffer with null buffer: " << index;
211*993b0882SAndroid Build Coastguard Worker     lua_error(state_);
212*993b0882SAndroid Build Coastguard Worker     return LUA_ERRRUN;
213*993b0882SAndroid Build Coastguard Worker   }
214*993b0882SAndroid Build Coastguard Worker   if (lua_type(state_, /*idx=*/index) != LUA_TTABLE) {
215*993b0882SAndroid Build Coastguard Worker     TC3_LOG(ERROR) << "Expected table, got: "
216*993b0882SAndroid Build Coastguard Worker                    << lua_type(state_, /*idx=*/kIndexStackTop);
217*993b0882SAndroid Build Coastguard Worker     lua_error(state_);
218*993b0882SAndroid Build Coastguard Worker     return LUA_ERRRUN;
219*993b0882SAndroid Build Coastguard Worker   }
220*993b0882SAndroid Build Coastguard Worker 
221*993b0882SAndroid Build Coastguard Worker   lua_pushnil(state_);
222*993b0882SAndroid Build Coastguard Worker   while (Next(index - 1)) {
223*993b0882SAndroid Build Coastguard Worker     const StringPiece key = ReadString(/*index=*/index - 1);
224*993b0882SAndroid Build Coastguard Worker     const reflection::Field* field = buffer->GetFieldOrNull(key);
225*993b0882SAndroid Build Coastguard Worker     if (field == nullptr) {
226*993b0882SAndroid Build Coastguard Worker       TC3_LOG(ERROR) << "Unknown field: " << key;
227*993b0882SAndroid Build Coastguard Worker       lua_error(state_);
228*993b0882SAndroid Build Coastguard Worker       return LUA_ERRRUN;
229*993b0882SAndroid Build Coastguard Worker     }
230*993b0882SAndroid Build Coastguard Worker     switch (field->type()->base_type()) {
231*993b0882SAndroid Build Coastguard Worker       case reflection::Obj:
232*993b0882SAndroid Build Coastguard Worker         ReadFlatbuffer(/*index=*/kIndexStackTop, buffer->Mutable(field));
233*993b0882SAndroid Build Coastguard Worker         break;
234*993b0882SAndroid Build Coastguard Worker       case reflection::Bool:
235*993b0882SAndroid Build Coastguard Worker         buffer->Set(field, Read<bool>(/*index=*/kIndexStackTop));
236*993b0882SAndroid Build Coastguard Worker         break;
237*993b0882SAndroid Build Coastguard Worker       case reflection::Byte:
238*993b0882SAndroid Build Coastguard Worker         buffer->Set(field, Read<int8>(/*index=*/kIndexStackTop));
239*993b0882SAndroid Build Coastguard Worker         break;
240*993b0882SAndroid Build Coastguard Worker       case reflection::UByte:
241*993b0882SAndroid Build Coastguard Worker         buffer->Set(field, Read<uint8>(/*index=*/kIndexStackTop));
242*993b0882SAndroid Build Coastguard Worker         break;
243*993b0882SAndroid Build Coastguard Worker       case reflection::Int:
244*993b0882SAndroid Build Coastguard Worker         buffer->Set(field, Read<int32>(/*index=*/kIndexStackTop));
245*993b0882SAndroid Build Coastguard Worker         break;
246*993b0882SAndroid Build Coastguard Worker       case reflection::UInt:
247*993b0882SAndroid Build Coastguard Worker         buffer->Set(field, Read<uint32>(/*index=*/kIndexStackTop));
248*993b0882SAndroid Build Coastguard Worker         break;
249*993b0882SAndroid Build Coastguard Worker       case reflection::Long:
250*993b0882SAndroid Build Coastguard Worker         buffer->Set(field, Read<int64>(/*index=*/kIndexStackTop));
251*993b0882SAndroid Build Coastguard Worker         break;
252*993b0882SAndroid Build Coastguard Worker       case reflection::ULong:
253*993b0882SAndroid Build Coastguard Worker         buffer->Set(field, Read<uint64>(/*index=*/kIndexStackTop));
254*993b0882SAndroid Build Coastguard Worker         break;
255*993b0882SAndroid Build Coastguard Worker       case reflection::Float:
256*993b0882SAndroid Build Coastguard Worker         buffer->Set(field, Read<float>(/*index=*/kIndexStackTop));
257*993b0882SAndroid Build Coastguard Worker         break;
258*993b0882SAndroid Build Coastguard Worker       case reflection::Double:
259*993b0882SAndroid Build Coastguard Worker         buffer->Set(field, Read<double>(/*index=*/kIndexStackTop));
260*993b0882SAndroid Build Coastguard Worker         break;
261*993b0882SAndroid Build Coastguard Worker       case reflection::String: {
262*993b0882SAndroid Build Coastguard Worker         buffer->Set(field, ReadString(/*index=*/kIndexStackTop));
263*993b0882SAndroid Build Coastguard Worker         break;
264*993b0882SAndroid Build Coastguard Worker       }
265*993b0882SAndroid Build Coastguard Worker       case reflection::Vector: {
266*993b0882SAndroid Build Coastguard Worker         // Read repeated field.
267*993b0882SAndroid Build Coastguard Worker         switch (field->type()->element()) {
268*993b0882SAndroid Build Coastguard Worker           case reflection::Bool:
269*993b0882SAndroid Build Coastguard Worker             ReadRepeatedField<bool>(/*index=*/kIndexStackTop,
270*993b0882SAndroid Build Coastguard Worker                                     buffer->Repeated(field));
271*993b0882SAndroid Build Coastguard Worker             break;
272*993b0882SAndroid Build Coastguard Worker           case reflection::Byte:
273*993b0882SAndroid Build Coastguard Worker             ReadRepeatedField<int8>(/*index=*/kIndexStackTop,
274*993b0882SAndroid Build Coastguard Worker                                     buffer->Repeated(field));
275*993b0882SAndroid Build Coastguard Worker             break;
276*993b0882SAndroid Build Coastguard Worker           case reflection::UByte:
277*993b0882SAndroid Build Coastguard Worker             ReadRepeatedField<uint8>(/*index=*/kIndexStackTop,
278*993b0882SAndroid Build Coastguard Worker                                      buffer->Repeated(field));
279*993b0882SAndroid Build Coastguard Worker             break;
280*993b0882SAndroid Build Coastguard Worker           case reflection::Int:
281*993b0882SAndroid Build Coastguard Worker             ReadRepeatedField<int32>(/*index=*/kIndexStackTop,
282*993b0882SAndroid Build Coastguard Worker                                      buffer->Repeated(field));
283*993b0882SAndroid Build Coastguard Worker             break;
284*993b0882SAndroid Build Coastguard Worker           case reflection::UInt:
285*993b0882SAndroid Build Coastguard Worker             ReadRepeatedField<uint32>(/*index=*/kIndexStackTop,
286*993b0882SAndroid Build Coastguard Worker                                       buffer->Repeated(field));
287*993b0882SAndroid Build Coastguard Worker             break;
288*993b0882SAndroid Build Coastguard Worker           case reflection::Long:
289*993b0882SAndroid Build Coastguard Worker             ReadRepeatedField<int64>(/*index=*/kIndexStackTop,
290*993b0882SAndroid Build Coastguard Worker                                      buffer->Repeated(field));
291*993b0882SAndroid Build Coastguard Worker             break;
292*993b0882SAndroid Build Coastguard Worker           case reflection::ULong:
293*993b0882SAndroid Build Coastguard Worker             ReadRepeatedField<uint64>(/*index=*/kIndexStackTop,
294*993b0882SAndroid Build Coastguard Worker                                       buffer->Repeated(field));
295*993b0882SAndroid Build Coastguard Worker             break;
296*993b0882SAndroid Build Coastguard Worker           case reflection::Float:
297*993b0882SAndroid Build Coastguard Worker             ReadRepeatedField<float>(/*index=*/kIndexStackTop,
298*993b0882SAndroid Build Coastguard Worker                                      buffer->Repeated(field));
299*993b0882SAndroid Build Coastguard Worker             break;
300*993b0882SAndroid Build Coastguard Worker           case reflection::Double:
301*993b0882SAndroid Build Coastguard Worker             ReadRepeatedField<double>(/*index=*/kIndexStackTop,
302*993b0882SAndroid Build Coastguard Worker                                       buffer->Repeated(field));
303*993b0882SAndroid Build Coastguard Worker             break;
304*993b0882SAndroid Build Coastguard Worker           case reflection::String:
305*993b0882SAndroid Build Coastguard Worker             ReadRepeatedField<std::string>(/*index=*/kIndexStackTop,
306*993b0882SAndroid Build Coastguard Worker                                            buffer->Repeated(field));
307*993b0882SAndroid Build Coastguard Worker             break;
308*993b0882SAndroid Build Coastguard Worker           case reflection::Obj:
309*993b0882SAndroid Build Coastguard Worker             ReadRepeatedField<MutableFlatbuffer>(/*index=*/kIndexStackTop,
310*993b0882SAndroid Build Coastguard Worker                                                  buffer->Repeated(field));
311*993b0882SAndroid Build Coastguard Worker             break;
312*993b0882SAndroid Build Coastguard Worker           default:
313*993b0882SAndroid Build Coastguard Worker             TC3_LOG(ERROR) << "Unsupported repeated field type: "
314*993b0882SAndroid Build Coastguard Worker                            << field->type()->element();
315*993b0882SAndroid Build Coastguard Worker             lua_error(state_);
316*993b0882SAndroid Build Coastguard Worker             return LUA_ERRRUN;
317*993b0882SAndroid Build Coastguard Worker         }
318*993b0882SAndroid Build Coastguard Worker         break;
319*993b0882SAndroid Build Coastguard Worker       }
320*993b0882SAndroid Build Coastguard Worker       default:
321*993b0882SAndroid Build Coastguard Worker         TC3_LOG(ERROR) << "Unsupported type: " << field->type()->base_type();
322*993b0882SAndroid Build Coastguard Worker         lua_error(state_);
323*993b0882SAndroid Build Coastguard Worker         return LUA_ERRRUN;
324*993b0882SAndroid Build Coastguard Worker     }
325*993b0882SAndroid Build Coastguard Worker     lua_pop(state_, 1);
326*993b0882SAndroid Build Coastguard Worker   }
327*993b0882SAndroid Build Coastguard Worker   return LUA_OK;
328*993b0882SAndroid Build Coastguard Worker }
329*993b0882SAndroid Build Coastguard Worker 
LoadDefaultLibraries()330*993b0882SAndroid Build Coastguard Worker void LuaEnvironment::LoadDefaultLibraries() {
331*993b0882SAndroid Build Coastguard Worker   for (const luaL_Reg* lib = defaultlibs; lib->func; lib++) {
332*993b0882SAndroid Build Coastguard Worker     luaL_requiref(state_, lib->name, lib->func, 1);
333*993b0882SAndroid Build Coastguard Worker     lua_pop(state_, 1);  // Remove lib.
334*993b0882SAndroid Build Coastguard Worker   }
335*993b0882SAndroid Build Coastguard Worker }
336*993b0882SAndroid Build Coastguard Worker 
ReadString(const int index) const337*993b0882SAndroid Build Coastguard Worker StringPiece LuaEnvironment::ReadString(const int index) const {
338*993b0882SAndroid Build Coastguard Worker   size_t length = 0;
339*993b0882SAndroid Build Coastguard Worker   const char* data = lua_tolstring(state_, index, &length);
340*993b0882SAndroid Build Coastguard Worker   return StringPiece(data, length);
341*993b0882SAndroid Build Coastguard Worker }
342*993b0882SAndroid Build Coastguard Worker 
PushString(const StringPiece str) const343*993b0882SAndroid Build Coastguard Worker void LuaEnvironment::PushString(const StringPiece str) const {
344*993b0882SAndroid Build Coastguard Worker   lua_pushlstring(state_, str.data(), str.size());
345*993b0882SAndroid Build Coastguard Worker }
346*993b0882SAndroid Build Coastguard Worker 
Compile(StringPiece snippet,std::string * bytecode) const347*993b0882SAndroid Build Coastguard Worker bool LuaEnvironment::Compile(StringPiece snippet, std::string* bytecode) const {
348*993b0882SAndroid Build Coastguard Worker   if (luaL_loadbuffer(state_, snippet.data(), snippet.size(),
349*993b0882SAndroid Build Coastguard Worker                       /*name=*/nullptr) != LUA_OK) {
350*993b0882SAndroid Build Coastguard Worker     TC3_LOG(ERROR) << "Could not compile lua snippet: "
351*993b0882SAndroid Build Coastguard Worker                    << ReadString(/*index=*/kIndexStackTop);
352*993b0882SAndroid Build Coastguard Worker     lua_pop(state_, 1);
353*993b0882SAndroid Build Coastguard Worker     return false;
354*993b0882SAndroid Build Coastguard Worker   }
355*993b0882SAndroid Build Coastguard Worker   if (lua_dump(state_, LuaStringWriter, bytecode, /*strip*/ 1) != LUA_OK) {
356*993b0882SAndroid Build Coastguard Worker     TC3_LOG(ERROR) << "Could not dump compiled lua snippet.";
357*993b0882SAndroid Build Coastguard Worker     lua_pop(state_, 1);
358*993b0882SAndroid Build Coastguard Worker     return false;
359*993b0882SAndroid Build Coastguard Worker   }
360*993b0882SAndroid Build Coastguard Worker   lua_pop(state_, 1);
361*993b0882SAndroid Build Coastguard Worker   return true;
362*993b0882SAndroid Build Coastguard Worker }
363*993b0882SAndroid Build Coastguard Worker 
PushAnnotation(const ClassificationResult & classification,const reflection::Schema * entity_data_schema) const364*993b0882SAndroid Build Coastguard Worker void LuaEnvironment::PushAnnotation(
365*993b0882SAndroid Build Coastguard Worker     const ClassificationResult& classification,
366*993b0882SAndroid Build Coastguard Worker     const reflection::Schema* entity_data_schema) const {
367*993b0882SAndroid Build Coastguard Worker   if (entity_data_schema == nullptr ||
368*993b0882SAndroid Build Coastguard Worker       classification.serialized_entity_data.empty()) {
369*993b0882SAndroid Build Coastguard Worker     // Empty table.
370*993b0882SAndroid Build Coastguard Worker     lua_newtable(state_);
371*993b0882SAndroid Build Coastguard Worker   } else {
372*993b0882SAndroid Build Coastguard Worker     PushFlatbuffer(entity_data_schema,
373*993b0882SAndroid Build Coastguard Worker                    flatbuffers::GetRoot<flatbuffers::Table>(
374*993b0882SAndroid Build Coastguard Worker                        classification.serialized_entity_data.data()));
375*993b0882SAndroid Build Coastguard Worker   }
376*993b0882SAndroid Build Coastguard Worker   Push(classification.datetime_parse_result.time_ms_utc);
377*993b0882SAndroid Build Coastguard Worker   lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kTimeUsecKey);
378*993b0882SAndroid Build Coastguard Worker   Push(classification.datetime_parse_result.granularity);
379*993b0882SAndroid Build Coastguard Worker   lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kGranularityKey);
380*993b0882SAndroid Build Coastguard Worker   Push(classification.collection);
381*993b0882SAndroid Build Coastguard Worker   lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kCollectionKey);
382*993b0882SAndroid Build Coastguard Worker   Push(classification.score);
383*993b0882SAndroid Build Coastguard Worker   lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kScoreKey);
384*993b0882SAndroid Build Coastguard Worker   Push(classification.serialized_entity_data);
385*993b0882SAndroid Build Coastguard Worker   lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kSerializedEntity);
386*993b0882SAndroid Build Coastguard Worker }
387*993b0882SAndroid Build Coastguard Worker 
PushAnnotation(const ClassificationResult & classification,StringPiece text,const reflection::Schema * entity_data_schema) const388*993b0882SAndroid Build Coastguard Worker void LuaEnvironment::PushAnnotation(
389*993b0882SAndroid Build Coastguard Worker     const ClassificationResult& classification, StringPiece text,
390*993b0882SAndroid Build Coastguard Worker     const reflection::Schema* entity_data_schema) const {
391*993b0882SAndroid Build Coastguard Worker   PushAnnotation(classification, entity_data_schema);
392*993b0882SAndroid Build Coastguard Worker   Push(text);
393*993b0882SAndroid Build Coastguard Worker   lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kTextKey);
394*993b0882SAndroid Build Coastguard Worker }
395*993b0882SAndroid Build Coastguard Worker 
PushAnnotation(const ActionSuggestionAnnotation & annotation,const reflection::Schema * entity_data_schema) const396*993b0882SAndroid Build Coastguard Worker void LuaEnvironment::PushAnnotation(
397*993b0882SAndroid Build Coastguard Worker     const ActionSuggestionAnnotation& annotation,
398*993b0882SAndroid Build Coastguard Worker     const reflection::Schema* entity_data_schema) const {
399*993b0882SAndroid Build Coastguard Worker   PushAnnotation(annotation.entity, annotation.span.text, entity_data_schema);
400*993b0882SAndroid Build Coastguard Worker   PushString(annotation.name);
401*993b0882SAndroid Build Coastguard Worker   lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kNameKey);
402*993b0882SAndroid Build Coastguard Worker   {
403*993b0882SAndroid Build Coastguard Worker     lua_newtable(state_);
404*993b0882SAndroid Build Coastguard Worker     Push(annotation.span.message_index);
405*993b0882SAndroid Build Coastguard Worker     lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kMessageKey);
406*993b0882SAndroid Build Coastguard Worker     Push(annotation.span.span.first);
407*993b0882SAndroid Build Coastguard Worker     lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kBeginKey);
408*993b0882SAndroid Build Coastguard Worker     Push(annotation.span.span.second);
409*993b0882SAndroid Build Coastguard Worker     lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kEndKey);
410*993b0882SAndroid Build Coastguard Worker   }
411*993b0882SAndroid Build Coastguard Worker   lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kSpanKey);
412*993b0882SAndroid Build Coastguard Worker }
413*993b0882SAndroid Build Coastguard Worker 
PushAnnotatedSpan(const AnnotatedSpan & annotated_span,const reflection::Schema * entity_data_schema) const414*993b0882SAndroid Build Coastguard Worker void LuaEnvironment::PushAnnotatedSpan(
415*993b0882SAndroid Build Coastguard Worker     const AnnotatedSpan& annotated_span,
416*993b0882SAndroid Build Coastguard Worker     const reflection::Schema* entity_data_schema) const {
417*993b0882SAndroid Build Coastguard Worker   lua_newtable(state_);
418*993b0882SAndroid Build Coastguard Worker   {
419*993b0882SAndroid Build Coastguard Worker     lua_newtable(state_);
420*993b0882SAndroid Build Coastguard Worker     Push(annotated_span.span.first);
421*993b0882SAndroid Build Coastguard Worker     lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kBeginKey);
422*993b0882SAndroid Build Coastguard Worker     Push(annotated_span.span.second);
423*993b0882SAndroid Build Coastguard Worker     lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kEndKey);
424*993b0882SAndroid Build Coastguard Worker   }
425*993b0882SAndroid Build Coastguard Worker   lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kSpanKey);
426*993b0882SAndroid Build Coastguard Worker   PushAnnotations(&annotated_span.classification, entity_data_schema);
427*993b0882SAndroid Build Coastguard Worker   lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kClassificationKey);
428*993b0882SAndroid Build Coastguard Worker }
429*993b0882SAndroid Build Coastguard Worker 
PushAnnotatedSpans(const std::vector<AnnotatedSpan> * annotated_spans,const reflection::Schema * entity_data_schema) const430*993b0882SAndroid Build Coastguard Worker void LuaEnvironment::PushAnnotatedSpans(
431*993b0882SAndroid Build Coastguard Worker     const std::vector<AnnotatedSpan>* annotated_spans,
432*993b0882SAndroid Build Coastguard Worker     const reflection::Schema* entity_data_schema) const {
433*993b0882SAndroid Build Coastguard Worker   PushIterator(annotated_spans ? annotated_spans->size() : 0,
434*993b0882SAndroid Build Coastguard Worker                [this, annotated_spans, entity_data_schema](const int64 index) {
435*993b0882SAndroid Build Coastguard Worker                  PushAnnotatedSpan(annotated_spans->at(index),
436*993b0882SAndroid Build Coastguard Worker                                    entity_data_schema);
437*993b0882SAndroid Build Coastguard Worker                  return 1;
438*993b0882SAndroid Build Coastguard Worker                });
439*993b0882SAndroid Build Coastguard Worker }
440*993b0882SAndroid Build Coastguard Worker 
ReadSpan() const441*993b0882SAndroid Build Coastguard Worker MessageTextSpan LuaEnvironment::ReadSpan() const {
442*993b0882SAndroid Build Coastguard Worker   MessageTextSpan span;
443*993b0882SAndroid Build Coastguard Worker   lua_pushnil(state_);
444*993b0882SAndroid Build Coastguard Worker   while (Next(/*index=*/kIndexStackTop - 1)) {
445*993b0882SAndroid Build Coastguard Worker     const StringPiece key = ReadString(/*index=*/kIndexStackTop - 1);
446*993b0882SAndroid Build Coastguard Worker     if (key.Equals(kMessageKey)) {
447*993b0882SAndroid Build Coastguard Worker       span.message_index = Read<int>(/*index=*/kIndexStackTop);
448*993b0882SAndroid Build Coastguard Worker     } else if (key.Equals(kBeginKey)) {
449*993b0882SAndroid Build Coastguard Worker       span.span.first = Read<int>(/*index=*/kIndexStackTop);
450*993b0882SAndroid Build Coastguard Worker     } else if (key.Equals(kEndKey)) {
451*993b0882SAndroid Build Coastguard Worker       span.span.second = Read<int>(/*index=*/kIndexStackTop);
452*993b0882SAndroid Build Coastguard Worker     } else if (key.Equals(kTextKey)) {
453*993b0882SAndroid Build Coastguard Worker       span.text = Read<std::string>(/*index=*/kIndexStackTop);
454*993b0882SAndroid Build Coastguard Worker     } else {
455*993b0882SAndroid Build Coastguard Worker       TC3_LOG(INFO) << "Unknown span field: " << key;
456*993b0882SAndroid Build Coastguard Worker     }
457*993b0882SAndroid Build Coastguard Worker     lua_pop(state_, 1);
458*993b0882SAndroid Build Coastguard Worker   }
459*993b0882SAndroid Build Coastguard Worker   return span;
460*993b0882SAndroid Build Coastguard Worker }
461*993b0882SAndroid Build Coastguard Worker 
ReadAnnotations(const reflection::Schema * entity_data_schema,std::vector<ActionSuggestionAnnotation> * annotations) const462*993b0882SAndroid Build Coastguard Worker int LuaEnvironment::ReadAnnotations(
463*993b0882SAndroid Build Coastguard Worker     const reflection::Schema* entity_data_schema,
464*993b0882SAndroid Build Coastguard Worker     std::vector<ActionSuggestionAnnotation>* annotations) const {
465*993b0882SAndroid Build Coastguard Worker   if (lua_type(state_, /*idx=*/kIndexStackTop) != LUA_TTABLE) {
466*993b0882SAndroid Build Coastguard Worker     TC3_LOG(ERROR) << "Expected annotations table, got: "
467*993b0882SAndroid Build Coastguard Worker                    << lua_type(state_, /*idx=*/kIndexStackTop);
468*993b0882SAndroid Build Coastguard Worker     lua_pop(state_, 1);
469*993b0882SAndroid Build Coastguard Worker     lua_error(state_);
470*993b0882SAndroid Build Coastguard Worker     return LUA_ERRRUN;
471*993b0882SAndroid Build Coastguard Worker   }
472*993b0882SAndroid Build Coastguard Worker 
473*993b0882SAndroid Build Coastguard Worker   // Read actions.
474*993b0882SAndroid Build Coastguard Worker   lua_pushnil(state_);
475*993b0882SAndroid Build Coastguard Worker   while (Next(/*index=*/kIndexStackTop - 1)) {
476*993b0882SAndroid Build Coastguard Worker     if (lua_type(state_, /*idx=*/kIndexStackTop) != LUA_TTABLE) {
477*993b0882SAndroid Build Coastguard Worker       TC3_LOG(ERROR) << "Expected annotation table, got: "
478*993b0882SAndroid Build Coastguard Worker                      << lua_type(state_, /*idx=*/kIndexStackTop);
479*993b0882SAndroid Build Coastguard Worker       lua_pop(state_, 1);
480*993b0882SAndroid Build Coastguard Worker       continue;
481*993b0882SAndroid Build Coastguard Worker     }
482*993b0882SAndroid Build Coastguard Worker     annotations->push_back(ReadAnnotation(entity_data_schema));
483*993b0882SAndroid Build Coastguard Worker     lua_pop(state_, 1);
484*993b0882SAndroid Build Coastguard Worker   }
485*993b0882SAndroid Build Coastguard Worker   return LUA_OK;
486*993b0882SAndroid Build Coastguard Worker }
487*993b0882SAndroid Build Coastguard Worker 
ReadAnnotation(const reflection::Schema * entity_data_schema) const488*993b0882SAndroid Build Coastguard Worker ActionSuggestionAnnotation LuaEnvironment::ReadAnnotation(
489*993b0882SAndroid Build Coastguard Worker     const reflection::Schema* entity_data_schema) const {
490*993b0882SAndroid Build Coastguard Worker   ActionSuggestionAnnotation annotation;
491*993b0882SAndroid Build Coastguard Worker   lua_pushnil(state_);
492*993b0882SAndroid Build Coastguard Worker   while (Next(/*index=*/kIndexStackTop - 1)) {
493*993b0882SAndroid Build Coastguard Worker     const StringPiece key = ReadString(/*index=*/kIndexStackTop - 1);
494*993b0882SAndroid Build Coastguard Worker     if (key.Equals(kNameKey)) {
495*993b0882SAndroid Build Coastguard Worker       annotation.name = Read<std::string>(/*index=*/kIndexStackTop);
496*993b0882SAndroid Build Coastguard Worker     } else if (key.Equals(kSpanKey)) {
497*993b0882SAndroid Build Coastguard Worker       annotation.span = ReadSpan();
498*993b0882SAndroid Build Coastguard Worker     } else if (key.Equals(kEntityKey)) {
499*993b0882SAndroid Build Coastguard Worker       annotation.entity = ReadClassificationResult(entity_data_schema);
500*993b0882SAndroid Build Coastguard Worker     } else {
501*993b0882SAndroid Build Coastguard Worker       TC3_LOG(ERROR) << "Unknown annotation field: " << key;
502*993b0882SAndroid Build Coastguard Worker     }
503*993b0882SAndroid Build Coastguard Worker     lua_pop(state_, 1);
504*993b0882SAndroid Build Coastguard Worker   }
505*993b0882SAndroid Build Coastguard Worker   return annotation;
506*993b0882SAndroid Build Coastguard Worker }
507*993b0882SAndroid Build Coastguard Worker 
ReadClassificationResult(const reflection::Schema * entity_data_schema) const508*993b0882SAndroid Build Coastguard Worker ClassificationResult LuaEnvironment::ReadClassificationResult(
509*993b0882SAndroid Build Coastguard Worker     const reflection::Schema* entity_data_schema) const {
510*993b0882SAndroid Build Coastguard Worker   ClassificationResult classification;
511*993b0882SAndroid Build Coastguard Worker   lua_pushnil(state_);
512*993b0882SAndroid Build Coastguard Worker   while (Next(/*index=*/kIndexStackTop - 1)) {
513*993b0882SAndroid Build Coastguard Worker     const StringPiece key = ReadString(/*index=*/kIndexStackTop - 1);
514*993b0882SAndroid Build Coastguard Worker     if (key.Equals(kCollectionKey)) {
515*993b0882SAndroid Build Coastguard Worker       classification.collection = Read<std::string>(/*index=*/kIndexStackTop);
516*993b0882SAndroid Build Coastguard Worker     } else if (key.Equals(kScoreKey)) {
517*993b0882SAndroid Build Coastguard Worker       classification.score = Read<float>(/*index=*/kIndexStackTop);
518*993b0882SAndroid Build Coastguard Worker     } else if (key.Equals(kTimeUsecKey)) {
519*993b0882SAndroid Build Coastguard Worker       classification.datetime_parse_result.time_ms_utc =
520*993b0882SAndroid Build Coastguard Worker           Read<int64>(/*index=*/kIndexStackTop);
521*993b0882SAndroid Build Coastguard Worker     } else if (key.Equals(kGranularityKey)) {
522*993b0882SAndroid Build Coastguard Worker       classification.datetime_parse_result.granularity =
523*993b0882SAndroid Build Coastguard Worker           static_cast<DatetimeGranularity>(
524*993b0882SAndroid Build Coastguard Worker               lua_tonumber(state_, /*idx=*/kIndexStackTop));
525*993b0882SAndroid Build Coastguard Worker     } else if (key.Equals(kSerializedEntity)) {
526*993b0882SAndroid Build Coastguard Worker       classification.serialized_entity_data =
527*993b0882SAndroid Build Coastguard Worker           Read<std::string>(/*index=*/kIndexStackTop);
528*993b0882SAndroid Build Coastguard Worker     } else if (key.Equals(kEntityKey)) {
529*993b0882SAndroid Build Coastguard Worker       auto buffer = MutableFlatbufferBuilder(entity_data_schema).NewRoot();
530*993b0882SAndroid Build Coastguard Worker       ReadFlatbuffer(/*index=*/kIndexStackTop, buffer.get());
531*993b0882SAndroid Build Coastguard Worker       classification.serialized_entity_data = buffer->Serialize();
532*993b0882SAndroid Build Coastguard Worker     } else {
533*993b0882SAndroid Build Coastguard Worker       TC3_LOG(INFO) << "Unknown classification result field: " << key;
534*993b0882SAndroid Build Coastguard Worker     }
535*993b0882SAndroid Build Coastguard Worker     lua_pop(state_, 1);
536*993b0882SAndroid Build Coastguard Worker   }
537*993b0882SAndroid Build Coastguard Worker   return classification;
538*993b0882SAndroid Build Coastguard Worker }
539*993b0882SAndroid Build Coastguard Worker 
PushAction(const ActionSuggestion & action,const reflection::Schema * actions_entity_data_schema,const reflection::Schema * annotations_entity_data_schema) const540*993b0882SAndroid Build Coastguard Worker void LuaEnvironment::PushAction(
541*993b0882SAndroid Build Coastguard Worker     const ActionSuggestion& action,
542*993b0882SAndroid Build Coastguard Worker     const reflection::Schema* actions_entity_data_schema,
543*993b0882SAndroid Build Coastguard Worker     const reflection::Schema* annotations_entity_data_schema) const {
544*993b0882SAndroid Build Coastguard Worker   if (actions_entity_data_schema == nullptr ||
545*993b0882SAndroid Build Coastguard Worker       action.serialized_entity_data.empty()) {
546*993b0882SAndroid Build Coastguard Worker     // Empty table.
547*993b0882SAndroid Build Coastguard Worker     lua_newtable(state_);
548*993b0882SAndroid Build Coastguard Worker   } else {
549*993b0882SAndroid Build Coastguard Worker     PushFlatbuffer(actions_entity_data_schema,
550*993b0882SAndroid Build Coastguard Worker                    flatbuffers::GetRoot<flatbuffers::Table>(
551*993b0882SAndroid Build Coastguard Worker                        action.serialized_entity_data.data()));
552*993b0882SAndroid Build Coastguard Worker   }
553*993b0882SAndroid Build Coastguard Worker   PushString(action.type);
554*993b0882SAndroid Build Coastguard Worker   lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kTypeKey);
555*993b0882SAndroid Build Coastguard Worker   PushString(action.response_text);
556*993b0882SAndroid Build Coastguard Worker   lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kResponseTextKey);
557*993b0882SAndroid Build Coastguard Worker   Push(action.score);
558*993b0882SAndroid Build Coastguard Worker   lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kScoreKey);
559*993b0882SAndroid Build Coastguard Worker   Push(action.priority_score);
560*993b0882SAndroid Build Coastguard Worker   lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kPriorityScoreKey);
561*993b0882SAndroid Build Coastguard Worker   PushAnnotations(&action.annotations, annotations_entity_data_schema);
562*993b0882SAndroid Build Coastguard Worker   lua_setfield(state_, /*idx=*/kIndexStackTop - 1, kAnnotationKey);
563*993b0882SAndroid Build Coastguard Worker }
564*993b0882SAndroid Build Coastguard Worker 
PushActions(const std::vector<ActionSuggestion> * actions,const reflection::Schema * actions_entity_data_schema,const reflection::Schema * annotations_entity_data_schema) const565*993b0882SAndroid Build Coastguard Worker void LuaEnvironment::PushActions(
566*993b0882SAndroid Build Coastguard Worker     const std::vector<ActionSuggestion>* actions,
567*993b0882SAndroid Build Coastguard Worker     const reflection::Schema* actions_entity_data_schema,
568*993b0882SAndroid Build Coastguard Worker     const reflection::Schema* annotations_entity_data_schema) const {
569*993b0882SAndroid Build Coastguard Worker   PushIterator(actions ? actions->size() : 0,
570*993b0882SAndroid Build Coastguard Worker                [this, actions, actions_entity_data_schema,
571*993b0882SAndroid Build Coastguard Worker                 annotations_entity_data_schema](const int64 index) {
572*993b0882SAndroid Build Coastguard Worker                  PushAction(actions->at(index), actions_entity_data_schema,
573*993b0882SAndroid Build Coastguard Worker                             annotations_entity_data_schema);
574*993b0882SAndroid Build Coastguard Worker                  return 1;
575*993b0882SAndroid Build Coastguard Worker                });
576*993b0882SAndroid Build Coastguard Worker }
577*993b0882SAndroid Build Coastguard Worker 
ReadAction(const reflection::Schema * actions_entity_data_schema,const reflection::Schema * annotations_entity_data_schema) const578*993b0882SAndroid Build Coastguard Worker ActionSuggestion LuaEnvironment::ReadAction(
579*993b0882SAndroid Build Coastguard Worker     const reflection::Schema* actions_entity_data_schema,
580*993b0882SAndroid Build Coastguard Worker     const reflection::Schema* annotations_entity_data_schema) const {
581*993b0882SAndroid Build Coastguard Worker   ActionSuggestion action;
582*993b0882SAndroid Build Coastguard Worker   lua_pushnil(state_);
583*993b0882SAndroid Build Coastguard Worker   while (Next(/*index=*/kIndexStackTop - 1)) {
584*993b0882SAndroid Build Coastguard Worker     const StringPiece key = ReadString(/*index=*/kIndexStackTop - 1);
585*993b0882SAndroid Build Coastguard Worker     if (key.Equals(kResponseTextKey)) {
586*993b0882SAndroid Build Coastguard Worker       action.response_text = Read<std::string>(/*index=*/kIndexStackTop);
587*993b0882SAndroid Build Coastguard Worker     } else if (key.Equals(kTypeKey)) {
588*993b0882SAndroid Build Coastguard Worker       action.type = Read<std::string>(/*index=*/kIndexStackTop);
589*993b0882SAndroid Build Coastguard Worker     } else if (key.Equals(kScoreKey)) {
590*993b0882SAndroid Build Coastguard Worker       action.score = Read<float>(/*index=*/kIndexStackTop);
591*993b0882SAndroid Build Coastguard Worker     } else if (key.Equals(kPriorityScoreKey)) {
592*993b0882SAndroid Build Coastguard Worker       action.priority_score = Read<float>(/*index=*/kIndexStackTop);
593*993b0882SAndroid Build Coastguard Worker     } else if (key.Equals(kAnnotationKey)) {
594*993b0882SAndroid Build Coastguard Worker       ReadAnnotations(actions_entity_data_schema, &action.annotations);
595*993b0882SAndroid Build Coastguard Worker     } else if (key.Equals(kEntityKey)) {
596*993b0882SAndroid Build Coastguard Worker       auto buffer =
597*993b0882SAndroid Build Coastguard Worker           MutableFlatbufferBuilder(actions_entity_data_schema).NewRoot();
598*993b0882SAndroid Build Coastguard Worker       ReadFlatbuffer(/*index=*/kIndexStackTop, buffer.get());
599*993b0882SAndroid Build Coastguard Worker       action.serialized_entity_data = buffer->Serialize();
600*993b0882SAndroid Build Coastguard Worker     } else {
601*993b0882SAndroid Build Coastguard Worker       TC3_LOG(INFO) << "Unknown action field: " << key;
602*993b0882SAndroid Build Coastguard Worker     }
603*993b0882SAndroid Build Coastguard Worker     lua_pop(state_, 1);
604*993b0882SAndroid Build Coastguard Worker   }
605*993b0882SAndroid Build Coastguard Worker   return action;
606*993b0882SAndroid Build Coastguard Worker }
607*993b0882SAndroid Build Coastguard Worker 
ReadActions(const reflection::Schema * actions_entity_data_schema,const reflection::Schema * annotations_entity_data_schema,std::vector<ActionSuggestion> * actions) const608*993b0882SAndroid Build Coastguard Worker int LuaEnvironment::ReadActions(
609*993b0882SAndroid Build Coastguard Worker     const reflection::Schema* actions_entity_data_schema,
610*993b0882SAndroid Build Coastguard Worker     const reflection::Schema* annotations_entity_data_schema,
611*993b0882SAndroid Build Coastguard Worker     std::vector<ActionSuggestion>* actions) const {
612*993b0882SAndroid Build Coastguard Worker   // Read actions.
613*993b0882SAndroid Build Coastguard Worker   lua_pushnil(state_);
614*993b0882SAndroid Build Coastguard Worker   while (Next(/*index=*/kIndexStackTop - 1)) {
615*993b0882SAndroid Build Coastguard Worker     if (lua_type(state_, /*idx=*/kIndexStackTop) != LUA_TTABLE) {
616*993b0882SAndroid Build Coastguard Worker       TC3_LOG(ERROR) << "Expected action table, got: "
617*993b0882SAndroid Build Coastguard Worker                      << lua_type(state_, /*idx=*/kIndexStackTop);
618*993b0882SAndroid Build Coastguard Worker       lua_pop(state_, 1);
619*993b0882SAndroid Build Coastguard Worker       continue;
620*993b0882SAndroid Build Coastguard Worker     }
621*993b0882SAndroid Build Coastguard Worker     actions->push_back(
622*993b0882SAndroid Build Coastguard Worker         ReadAction(actions_entity_data_schema, annotations_entity_data_schema));
623*993b0882SAndroid Build Coastguard Worker     lua_pop(state_, /*n=*/1);
624*993b0882SAndroid Build Coastguard Worker   }
625*993b0882SAndroid Build Coastguard Worker   lua_pop(state_, /*n=*/1);
626*993b0882SAndroid Build Coastguard Worker 
627*993b0882SAndroid Build Coastguard Worker   return LUA_OK;
628*993b0882SAndroid Build Coastguard Worker }
629*993b0882SAndroid Build Coastguard Worker 
PushConversation(const std::vector<ConversationMessage> * conversation,const reflection::Schema * annotations_entity_data_schema) const630*993b0882SAndroid Build Coastguard Worker void LuaEnvironment::PushConversation(
631*993b0882SAndroid Build Coastguard Worker     const std::vector<ConversationMessage>* conversation,
632*993b0882SAndroid Build Coastguard Worker     const reflection::Schema* annotations_entity_data_schema) const {
633*993b0882SAndroid Build Coastguard Worker   PushIterator(
634*993b0882SAndroid Build Coastguard Worker       conversation ? conversation->size() : 0,
635*993b0882SAndroid Build Coastguard Worker       [this, conversation, annotations_entity_data_schema](const int64 index) {
636*993b0882SAndroid Build Coastguard Worker         const ConversationMessage& message = conversation->at(index);
637*993b0882SAndroid Build Coastguard Worker         lua_newtable(state_);
638*993b0882SAndroid Build Coastguard Worker         Push(message.user_id);
639*993b0882SAndroid Build Coastguard Worker         lua_setfield(state_, /*idx=*/kIndexStackTop - 1, "user_id");
640*993b0882SAndroid Build Coastguard Worker         Push(message.text);
641*993b0882SAndroid Build Coastguard Worker         lua_setfield(state_, /*idx=*/kIndexStackTop - 1, "text");
642*993b0882SAndroid Build Coastguard Worker         Push(message.reference_time_ms_utc);
643*993b0882SAndroid Build Coastguard Worker         lua_setfield(state_, /*idx=*/kIndexStackTop - 1, "time_ms_utc");
644*993b0882SAndroid Build Coastguard Worker         Push(message.reference_timezone);
645*993b0882SAndroid Build Coastguard Worker         lua_setfield(state_, /*idx=*/kIndexStackTop - 1, "timezone");
646*993b0882SAndroid Build Coastguard Worker         PushAnnotatedSpans(&message.annotations,
647*993b0882SAndroid Build Coastguard Worker                            annotations_entity_data_schema);
648*993b0882SAndroid Build Coastguard Worker         lua_setfield(state_, /*idx=*/kIndexStackTop - 1, "annotation");
649*993b0882SAndroid Build Coastguard Worker         return 1;
650*993b0882SAndroid Build Coastguard Worker       });
651*993b0882SAndroid Build Coastguard Worker }
652*993b0882SAndroid Build Coastguard Worker 
Compile(StringPiece snippet,std::string * bytecode)653*993b0882SAndroid Build Coastguard Worker bool Compile(StringPiece snippet, std::string* bytecode) {
654*993b0882SAndroid Build Coastguard Worker   return LuaEnvironment().Compile(snippet, bytecode);
655*993b0882SAndroid Build Coastguard Worker }
656*993b0882SAndroid Build Coastguard Worker 
657*993b0882SAndroid Build Coastguard Worker }  // namespace libtextclassifier3
658