You can assign one record value to another using simple assignment:
local a: conn_id; ... local b: conn_id; ... b = a;
Doing so produces a shallow copy. That is, after the assignment,
b
refers to the same record as does a
, and an assignment
to one of b
's fields will alter the field in a
's value
(and vice versa for an assignment to one of a
's fields).
However, assigning again to b
itself, or assigning to a
itself,
will break the connection.
Deficiency: Bro lacks a mechanism for specifying a deep copy, in which no linkage is connected between b
and a
. Consequently,
you must be careful when assigning records to ensure you account for
the shallow-copy semantics.
You can also assign to a record another record that has fields with the same names and types, even if they come in a different order. For example, if you have:
local b: conn_id; local c: record { resp_h: addr, orig_h: addr; resp_p: port, orig_p: port; };
then you can assign either b
to c
or vice versa.
You could not, however, make the assignment (in either direction) if you had:
local b: conn_id; local c: record { resp_h: addr, orig_h: addr; resp_p: port, orig_p: port; num_alerts: count; };
because the field num_alerts
would either be missing or excess.
However, when declaring a record you can associate attributes with the fields. The relevant ones are
&optional
,
which indicates that when assigning to the record you can omit the field, and
&default = expr
, which indicates
that if the field is missing, then a reference to it returns the value of the expression expr. So if instead you had:
local b: conn_id; local c: record { resp_h: addr, orig_h: addr; resp_p: port, orig_p: port; num_alerts: count &optional; };
then you could execute c = b
even though num_alerts
is missing from b.
You still could not execute b = c
,
though, since in that direction, num alerts is an extra field (regardless of whether it has
been assigned to or not — the error is a type-checking error, not a run-time error).
The same holds for:
local b: conn_id; local c: record { resp_h: addr, orig_h: addr; resp_p: port, orig_p: port; num_alerts: count &default = 0; };
I.e., you could execute c = b
but not b = c
. The only difference between this example and the previous one is that
for the previous one, access to c$num_alerts
without having first assigned to it
results in a run-time error, while in the second, it yields 0.
You can test for whether a record field exists using the ?$
operator.
Finally, all of the rules for assigning records also apply when passing a record value as an argument in a function call or an event handler invocation.