Derive Macro ZeekType
#[derive(ZeekType)]
Expand description
§Derive macro to convert a type from and to a zeek_websocket_types::Value
Zeek’s WebSocket API encodes Zeek record
values as vectors. This derive macro adds support
for automatically converting Rust types to and from the encoding. It supports struct
s
made up of fields which implement TryFrom<Value>
and Into<Value>
.
#[derive(Debug, PartialEq)] // Not required.
#[derive(ZeekType)]
struct Record {
a: i64,
b: u64,
}
let r = Record { a: -32, b: 1024 };
let value = Value::from(r);
assert_eq!(
value,
Value::Vector(vec![Value::Integer(-32), Value::Count(1024)]));
let r = Record::try_from(value).unwrap();
assert_eq!(r, Record { a: -32, b: 1024 });
If more than the expected number of fields are received they are silently discarded.
let v = Value::Vector(vec![Value::Integer(1), Value::Count(2), Value::Count(3)]);
let r: Record = v.try_into().unwrap();
assert_eq!(r, Record { a: 1, b: 2 });
// Unknown fields are not magically added back when encoding. This is supported by Zeek.
let v2 = Value::from(r);
assert_eq!(v2, Value::Vector(vec![Value::Integer(1), Value::Count(2)]));
§Optional fields
Zeek record
fields which can be unset are marked &optional
, e.g.,
type X: record {
a: count;
b: int &optional;
};
This is used to evolve Zeek record
types so that users do not need to be updated if
more fields are added.
The WebSocket API encodes unset fields as Value::None
. To work with such types the Rust type
should be an Option
, e.g.,
#[derive(ZeekType)]
struct X {
a: u64,
b: Option<i64>,
}
Value::None
maps onto Option::None
.
let v = Value::Vector(vec![Value::Count(1), Value::None]);
let x: X = v.try_into().unwrap();
assert_eq!(x, X { a: 1, b: None });
Anything else maps onto Option::Some
.
let v = Value::Vector(vec![Value::Count(1), Value::Integer(2)]);
let x: X = v.try_into().unwrap();
assert_eq!(x, X { a: 1, b: Some(2) });
If no value was received for an optional field it is set to None
. Non-Option
fields are
always required.
let v = Value::Vector(vec![Value::Count(1)]);
let x: X = v.try_into().unwrap();
assert_eq!(x, X { a: 1, b: None });
// Error for non-`Option` fields.
let x: Result<X, _> = Value::Vector(vec![]).try_into();
assert!(x.is_err());