Type/RecordType: Make table returned by GetRecordFieldsVal() ordered

Seems only reasonable to provide that guarantee as pointed out in #4674.
This commit is contained in:
Arne Welzel 2025-07-22 15:36:34 +02:00
parent db018253fe
commit 9f3a3b423f
9 changed files with 54 additions and 43 deletions

View file

@ -1213,7 +1213,12 @@ static string container_type_name(const Type* ft) {
TableValPtr RecordType::GetRecordFieldsVal(const RecordVal* rv) const {
static auto record_field = id::find_type<RecordType>("record_field");
static auto record_field_table = id::find_type<TableType>("record_field_table");
auto rval = make_intrusive<TableVal>(record_field_table);
auto attrs = zeek::make_intrusive<detail::Attributes>(record_field_table,
/*in_record=*/false,
/*is_global=*/false);
attrs->AddAttr(make_intrusive<detail::Attr>(detail::ATTR_ORDERED));
auto rval = make_intrusive<TableVal>(record_field_table, std::move(attrs));
for ( int i = 0; i < NumFields(); ++i ) {
const auto& ft = GetFieldType(i);

View file

@ -697,7 +697,10 @@ public:
/**
* Returns a "record_field_table" value for introspection purposes.
* @param rv an optional record value, if given the values of
* all fields will be provided in the returned table.
* all fields will be provided in the returned table. The table
* is initialized with the &ordered attribute such that iterating over
* the table will yield entries for fields in the same order as they
* are kept in the record type types list.
*/
TableValPtr GetRecordFieldsVal(const RecordVal* rv = nullptr) const;

View file

@ -2403,7 +2403,10 @@ function lookup_ID%(id: string%) : any
##
## rec: The record value or type to inspect.
##
## Returns: A table that describes the fields of a record.
## Returns: A table that describes the fields of a record. The returned table has
## the :zeek:attr:`&ordered` attribute set. Iterating over the table will
## yield entries for the fields in the same order as the fields were
## declared.
function record_fields%(rec: any%): record_field_table
%{
static auto record_field_table = zeek::id::find_type<zeek::TableType>("record_field_table");

View file

@ -2,9 +2,9 @@
[a=42, b=Foo, c=<uninitialized>, d=Bar, e=tt]
{
[a] = [type_name=count, log=F, value=42, default_val=<uninitialized>, optional=F],
[d] = [type_name=string, log=T, value=Bar, default_val=<uninitialized>, optional=F],
[b] = [type_name=string, log=F, value=Foo, default_val=Foo, optional=T],
[c] = [type_name=double, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=T],
[d] = [type_name=string, log=T, value=Bar, default_val=<uninitialized>, optional=F],
[e] = [type_name=any, log=F, value=tt, default_val=<uninitialized>, optional=F]
}
c value, F
@ -12,27 +12,27 @@ c default , F
c optional, T
{
[a] = [type_name=bool, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[d] = [type_name=string, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[f] = [type_name=enum Monochrome::color, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[b] = [type_name=string, log=F, value=<uninitialized>, default_val=Bar, optional=T],
[c] = [type_name=double, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=T],
[m] = [type_name=record myrec, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[e] = [type_name=enum color, log=F, value=<uninitialized>, default_val=BLUE, optional=T]
[d] = [type_name=string, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[e] = [type_name=enum color, log=F, value=<uninitialized>, default_val=BLUE, optional=T],
[f] = [type_name=enum Monochrome::color, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[m] = [type_name=record myrec, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F]
}
{
[a] = [type_name=bool, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[d] = [type_name=string, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[f] = [type_name=enum Monochrome::color, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[b] = [type_name=string, log=F, value=<uninitialized>, default_val=Bar, optional=T],
[c] = [type_name=double, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=T],
[m] = [type_name=record myrec, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[e] = [type_name=enum color, log=F, value=<uninitialized>, default_val=BLUE, optional=T]
[d] = [type_name=string, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[e] = [type_name=enum color, log=F, value=<uninitialized>, default_val=BLUE, optional=T],
[f] = [type_name=enum Monochrome::color, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[m] = [type_name=record myrec, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F]
}
{
[a] = [type_name=count, log=F, value=42, default_val=<uninitialized>, optional=F],
[d] = [type_name=string, log=T, value=Bar, default_val=<uninitialized>, optional=F],
[b] = [type_name=string, log=F, value=Foo, default_val=Foo, optional=T],
[c] = [type_name=double, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=T],
[d] = [type_name=string, log=T, value=Bar, default_val=<uninitialized>, optional=F],
[e] = [type_name=any, log=F, value=mystring, default_val=<uninitialized>, optional=F]
}
{
@ -43,26 +43,26 @@ c optional, T
}
{
[a] = [type_name=bool, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[d] = [type_name=string, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[f] = [type_name=enum Monochrome::color, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[b] = [type_name=string, log=F, value=<uninitialized>, default_val=Bar, optional=T],
[c] = [type_name=double, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=T],
[m] = [type_name=record myrec, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[e] = [type_name=enum color, log=F, value=<uninitialized>, default_val=BLUE, optional=T]
[d] = [type_name=string, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[e] = [type_name=enum color, log=F, value=<uninitialized>, default_val=BLUE, optional=T],
[f] = [type_name=enum Monochrome::color, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[m] = [type_name=record myrec, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F]
}
{
[a] = [type_name=count, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[d] = [type_name=string, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[b] = [type_name=string, log=F, value=<uninitialized>, default_val=Foo, optional=T],
[c] = [type_name=double, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=T],
[d] = [type_name=string, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[e] = [type_name=any, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F]
}
{
[a] = [type_name=set[double], log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[d] = [type_name=table[double,string] of table[string] of vector of string, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[f] = [type_name=vector of enum color, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[b] = [type_name=set[double,string], log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[c] = [type_name=set[double,record tt], log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[g] = [type_name=table[string] of enum color, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[e] = [type_name=vector of vector of string, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F]
[d] = [type_name=table[double,string] of table[string] of vector of string, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[e] = [type_name=vector of vector of string, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[f] = [type_name=vector of enum color, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[g] = [type_name=table[string] of enum color, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=F]
}

View file

@ -1,10 +1,10 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
Info record_fields\x0a, {
[ts] = [type_name=time, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[msg] = [type_name=string, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[extra1] = [type_name=string, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=T],
[extra2] = [type_name=string, log=F, value=<uninitialized>, default_val=<uninitialized>, optional=T],
[ts] = [type_name=time, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[extra3] = [type_name=string, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=T],
[msg] = [type_name=string, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=F],
[extra4] = [type_name=string, log=T, value=<uninitialized>, default_val=<uninitialized>, optional=T]
}
Info record, [ts=XXXXXXXXXX.XXXXXX, msg=msg, extra1=extra1 value, extra2=extra2 value, extra3=extra3 value, extra4=extra4 value]

View file

@ -5,6 +5,6 @@ Conn::Info$speculative_service, policy/protocols/conn/speculative-service.zeek
Conn::Info$orig_l2_addr, policy/protocols/conn/mac-logging.zeek
MyModule::Info, my-module.zeek
MyModule::Info$ts, original, my-module.zeek
MyModule::Info$prefix, original, my-module.zeek
MyModule::Info$addl, redef, redef-it.zeek
MyModule::Info$more, redef, pkg1/redef-more.zeek
MyModule::Info$prefix, original, my-module.zeek

View file

@ -2,14 +2,14 @@
{
[a] = [type_name=count, log=F, value=80, default_val=<uninitialized>, optional=T],
[bf] = [type_name=record , log=F, value=[x1=79, y1=15, z1=4], default_val=<uninitialized>, optional=T],
[x2] = [type_name=count, log=F, value=83, default_val=<uninitialized>, optional=T],
[y2] = [type_name=count, log=F, value=3, default_val=<uninitialized>, optional=T],
[z2] = [type_name=count, log=F, value=5, default_val=<uninitialized>, optional=T],
[x2] = [type_name=count, log=F, value=83, default_val=<uninitialized>, optional=T],
[b] = [type_name=count, log=F, value=84, default_val=<uninitialized>, optional=T]
}
{
[z1] = [type_name=count, log=F, value=4, default_val=<uninitialized>, optional=F],
[x1] = [type_name=count, log=F, value=79, default_val=<uninitialized>, optional=F],
[y1] = [type_name=count, log=F, value=15, default_val=<uninitialized>, optional=F],
[x1] = [type_name=count, log=F, value=79, default_val=<uninitialized>, optional=F]
[z1] = [type_name=count, log=F, value=4, default_val=<uninitialized>, optional=F]
}
[a=80, bf=[x1=79, y1=15, z1=4], x2=83, y2=3, z2=5, b=84]

View file

@ -3,12 +3,12 @@
name=x log=F
=== X1
name=x log=F
name=z log=F
name=y log=F
name=z log=F
=== X2
name=x log=T
name=z log=T
name=y log=T
name=z log=T
=== X3
name=x log=F
name=z log=T

View file

@ -8,26 +8,26 @@ Test::type_enum_C
Test::type_enum_Undef
Test::type_record_u, {
[s] = [type_name=string, log=F, value=<uninitialized>, default_val=<uninitialized>],
[u2] = [type_name=record , log=F, value=<uninitialized>, default_val=<uninitialized>],
[b] = [type_name=bool, log=F, value=<uninitialized>, default_val=<uninitialized>]
[b] = [type_name=bool, log=F, value=<uninitialized>, default_val=<uninitialized>],
[u2] = [type_name=record , log=F, value=<uninitialized>, default_val=<uninitialized>]
}
Test::u
Test::u2
XYZ::type_record_sss, {
[a] = [type_name=addr, log=F, value=<uninitialized>, default_val=<uninitialized>],
[v] = [type_name=vector of string, log=F, value=<uninitialized>, default_val=<uninitialized>],
[iv] = [type_name=interval, log=F, value=<uninitialized>, default_val=<uninitialized>],
[t] = [type_name=time, log=F, value=<uninitialized>, default_val=<uninitialized>],
[s] = [type_name=set[enum], log=F, value=<uninitialized>, default_val=<uninitialized>],
[p] = [type_name=port, log=F, value=<uninitialized>, default_val=<uninitialized>],
[b] = [type_name=string, log=F, value=<uninitialized>, default_val=<uninitialized>],
[i] = [type_name=int, log=F, value=<uninitialized>, default_val=<uninitialized>],
[o] = [type_name=string, log=F, value=<uninitialized>, default_val=<uninitialized>],
[m] = [type_name=table[addr] of string, log=F, value=<uninitialized>, default_val=<uninitialized>],
[u] = [type_name=record , log=F, value=<uninitialized>, default_val=<uninitialized>],
[j] = [type_name=count, log=F, value=<uninitialized>, default_val=<uninitialized>],
[e] = [type_name=enum, log=F, value=<uninitialized>, default_val=<uninitialized>],
[r] = [type_name=double, log=F, value=<uninitialized>, default_val=<uninitialized>]
[i] = [type_name=int, log=F, value=<uninitialized>, default_val=<uninitialized>],
[iv] = [type_name=interval, log=F, value=<uninitialized>, default_val=<uninitialized>],
[j] = [type_name=count, log=F, value=<uninitialized>, default_val=<uninitialized>],
[m] = [type_name=table[addr] of string, log=F, value=<uninitialized>, default_val=<uninitialized>],
[o] = [type_name=string, log=F, value=<uninitialized>, default_val=<uninitialized>],
[p] = [type_name=port, log=F, value=<uninitialized>, default_val=<uninitialized>],
[r] = [type_name=double, log=F, value=<uninitialized>, default_val=<uninitialized>],
[s] = [type_name=set[enum], log=F, value=<uninitialized>, default_val=<uninitialized>],
[t] = [type_name=time, log=F, value=<uninitialized>, default_val=<uninitialized>],
[u] = [type_name=record , log=F, value=<uninitialized>, default_val=<uninitialized>],
[v] = [type_name=vector of string, log=F, value=<uninitialized>, default_val=<uninitialized>]
}
type_record_u2, {
[t] = [type_name=record , log=F, value=<uninitialized>, default_val=<uninitialized>]