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 { TableValPtr RecordType::GetRecordFieldsVal(const RecordVal* rv) const {
static auto record_field = id::find_type<RecordType>("record_field"); static auto record_field = id::find_type<RecordType>("record_field");
static auto record_field_table = id::find_type<TableType>("record_field_table"); 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 ) { for ( int i = 0; i < NumFields(); ++i ) {
const auto& ft = GetFieldType(i); const auto& ft = GetFieldType(i);

View file

@ -697,7 +697,10 @@ public:
/** /**
* Returns a "record_field_table" value for introspection purposes. * Returns a "record_field_table" value for introspection purposes.
* @param rv an optional record value, if given the values of * @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; 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. ## 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 function record_fields%(rec: any%): record_field_table
%{ %{
static auto record_field_table = zeek::id::find_type<zeek::TableType>("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=42, b=Foo, c=<uninitialized>, d=Bar, e=tt]
{ {
[a] = [type_name=count, log=F, value=42, 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], [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], [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] [e] = [type_name=any, log=F, value=tt, default_val=<uninitialized>, optional=F]
} }
c value, F c value, F
@ -12,27 +12,27 @@ c default , F
c optional, T c optional, T
{ {
[a] = [type_name=bool, 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], [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], [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], [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] [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], [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], [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], [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], [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] [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], [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], [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], [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] [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], [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], [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], [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], [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] [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], [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], [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], [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] [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], [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], [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], [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], [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] [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. ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
Info record_fields\x0a, { 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], [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], [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], [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] [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] 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 Conn::Info$orig_l2_addr, policy/protocols/conn/mac-logging.zeek
MyModule::Info, my-module.zeek MyModule::Info, my-module.zeek
MyModule::Info$ts, original, 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$addl, redef, redef-it.zeek
MyModule::Info$more, redef, pkg1/redef-more.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], [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], [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], [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], [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] [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], [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] [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 name=x log=F
=== X1 === X1
name=x log=F name=x log=F
name=z log=F
name=y log=F name=y log=F
name=z log=F
=== X2 === X2
name=x log=T name=x log=T
name=z log=T
name=y log=T name=y log=T
name=z log=T
=== X3 === X3
name=x log=F name=x log=F
name=z log=T name=z log=T

View file

@ -8,26 +8,26 @@ Test::type_enum_C
Test::type_enum_Undef Test::type_enum_Undef
Test::type_record_u, { Test::type_record_u, {
[s] = [type_name=string, log=F, value=<uninitialized>, default_val=<uninitialized>], [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::u
Test::u2 Test::u2
XYZ::type_record_sss, { XYZ::type_record_sss, {
[a] = [type_name=addr, log=F, value=<uninitialized>, default_val=<uninitialized>], [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>], [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>], [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, { type_record_u2, {
[t] = [type_name=record , log=F, value=<uninitialized>, default_val=<uninitialized>] [t] = [type_name=record , log=F, value=<uninitialized>, default_val=<uninitialized>]