mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Spicy: Extend exception hierarchy.
We move the current `TypeMismatch` into a new `ParameterMismatch` exception that's derived from a more general `TypeMismatch` now that can also be used for other, non-parameter mismatches.
This commit is contained in:
parent
a7f10df4f7
commit
751c35b476
1 changed files with 44 additions and 37 deletions
|
@ -59,15 +59,22 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception thrown by event generation code if there's a type mismatch
|
* Exception thrown if there's a type mismatch between Spicy and Zeek side.
|
||||||
* between the Spicy-side value and what the Zeek event expects.
|
|
||||||
*/
|
*/
|
||||||
class TypeMismatch : public UsageError {
|
class TypeMismatch : public UsageError {
|
||||||
|
using UsageError::UsageError;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown by event generation code if there's a type mismatch between
|
||||||
|
* a Spicy-side parameter value and what the Zeek event expects.
|
||||||
|
*/
|
||||||
|
class ParameterMismatch : public TypeMismatch {
|
||||||
public:
|
public:
|
||||||
TypeMismatch(const std::string_view& msg, std::string_view location = "")
|
ParameterMismatch(const std::string_view& msg, std::string_view location = "")
|
||||||
: UsageError(hilti::rt::fmt("Event parameter mismatch, %s", msg)) {}
|
: TypeMismatch(hilti::rt::fmt("Event parameter mismatch, %s", msg)) {}
|
||||||
TypeMismatch(const std::string_view& have, const TypePtr& want, std::string_view location = "")
|
ParameterMismatch(const std::string_view& have, const TypePtr& want, std::string_view location = "")
|
||||||
: TypeMismatch(_fmt(have, want)) {}
|
: ParameterMismatch(_fmt(have, want)) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _fmt(const std::string_view& have, const TypePtr& want) {
|
std::string _fmt(const std::string_view& have, const TypePtr& want) {
|
||||||
|
@ -538,7 +545,7 @@ inline ValPtr to_val(const hilti::rt::DeferredExpression<T, E>& t, const TypePtr
|
||||||
*/
|
*/
|
||||||
inline ValPtr to_val(const std::string& s, const TypePtr& target) {
|
inline ValPtr to_val(const std::string& s, const TypePtr& target) {
|
||||||
if ( target->Tag() != TYPE_STRING )
|
if ( target->Tag() != TYPE_STRING )
|
||||||
throw TypeMismatch("string", target);
|
throw ParameterMismatch("string", target);
|
||||||
|
|
||||||
return make_intrusive<StringVal>(s);
|
return make_intrusive<StringVal>(s);
|
||||||
}
|
}
|
||||||
|
@ -549,7 +556,7 @@ inline ValPtr to_val(const std::string& s, const TypePtr& target) {
|
||||||
*/
|
*/
|
||||||
inline ValPtr to_val(const hilti::rt::Bytes& b, const TypePtr& target) {
|
inline ValPtr to_val(const hilti::rt::Bytes& b, const TypePtr& target) {
|
||||||
if ( target->Tag() != TYPE_STRING )
|
if ( target->Tag() != TYPE_STRING )
|
||||||
throw TypeMismatch("string", target);
|
throw ParameterMismatch("string", target);
|
||||||
|
|
||||||
return make_intrusive<StringVal>(b.str());
|
return make_intrusive<StringVal>(b.str());
|
||||||
}
|
}
|
||||||
|
@ -568,7 +575,7 @@ inline ValPtr to_val(hilti::rt::integer::safe<T> i, const TypePtr& target) {
|
||||||
if ( target->Tag() == TYPE_INT )
|
if ( target->Tag() == TYPE_INT )
|
||||||
return val_mgr->Int(i);
|
return val_mgr->Int(i);
|
||||||
|
|
||||||
throw TypeMismatch("uint64", target);
|
throw ParameterMismatch("uint64", target);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ( target->Tag() == TYPE_INT )
|
if ( target->Tag() == TYPE_INT )
|
||||||
|
@ -578,10 +585,10 @@ inline ValPtr to_val(hilti::rt::integer::safe<T> i, const TypePtr& target) {
|
||||||
if ( i >= 0 )
|
if ( i >= 0 )
|
||||||
return val_mgr->Count(i);
|
return val_mgr->Count(i);
|
||||||
else
|
else
|
||||||
throw TypeMismatch("negative int64", target);
|
throw ParameterMismatch("negative int64", target);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw TypeMismatch("int64", target);
|
throw ParameterMismatch("int64", target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,7 +606,7 @@ ValPtr to_val(const hilti::rt::ValueReference<T>& t, const TypePtr& target) {
|
||||||
*/
|
*/
|
||||||
inline ValPtr to_val(const hilti::rt::Bool& b, const TypePtr& target) {
|
inline ValPtr to_val(const hilti::rt::Bool& b, const TypePtr& target) {
|
||||||
if ( target->Tag() != TYPE_BOOL )
|
if ( target->Tag() != TYPE_BOOL )
|
||||||
throw TypeMismatch("bool", target);
|
throw ParameterMismatch("bool", target);
|
||||||
|
|
||||||
return val_mgr->Bool(b);
|
return val_mgr->Bool(b);
|
||||||
}
|
}
|
||||||
|
@ -610,7 +617,7 @@ inline ValPtr to_val(const hilti::rt::Bool& b, const TypePtr& target) {
|
||||||
*/
|
*/
|
||||||
inline ValPtr to_val(double r, const TypePtr& target) {
|
inline ValPtr to_val(double r, const TypePtr& target) {
|
||||||
if ( target->Tag() != TYPE_DOUBLE )
|
if ( target->Tag() != TYPE_DOUBLE )
|
||||||
throw TypeMismatch("double", target);
|
throw ParameterMismatch("double", target);
|
||||||
|
|
||||||
return make_intrusive<DoubleVal>(r);
|
return make_intrusive<DoubleVal>(r);
|
||||||
}
|
}
|
||||||
|
@ -621,7 +628,7 @@ inline ValPtr to_val(double r, const TypePtr& target) {
|
||||||
*/
|
*/
|
||||||
inline ValPtr to_val(const hilti::rt::Address& d, const TypePtr& target) {
|
inline ValPtr to_val(const hilti::rt::Address& d, const TypePtr& target) {
|
||||||
if ( target->Tag() != TYPE_ADDR )
|
if ( target->Tag() != TYPE_ADDR )
|
||||||
throw TypeMismatch("addr", target);
|
throw ParameterMismatch("addr", target);
|
||||||
|
|
||||||
auto in_addr = d.asInAddr();
|
auto in_addr = d.asInAddr();
|
||||||
if ( auto v4 = std::get_if<struct in_addr>(&in_addr) )
|
if ( auto v4 = std::get_if<struct in_addr>(&in_addr) )
|
||||||
|
@ -638,7 +645,7 @@ inline ValPtr to_val(const hilti::rt::Address& d, const TypePtr& target) {
|
||||||
*/
|
*/
|
||||||
inline ValPtr to_val(const hilti::rt::Port& p, const TypePtr& target) {
|
inline ValPtr to_val(const hilti::rt::Port& p, const TypePtr& target) {
|
||||||
if ( target->Tag() != TYPE_PORT )
|
if ( target->Tag() != TYPE_PORT )
|
||||||
throw TypeMismatch("port", target);
|
throw ParameterMismatch("port", target);
|
||||||
|
|
||||||
switch ( p.protocol().value() ) {
|
switch ( p.protocol().value() ) {
|
||||||
case hilti::rt::Protocol::TCP: return val_mgr->Port(p.port(), ::TransportProto::TRANSPORT_TCP);
|
case hilti::rt::Protocol::TCP: return val_mgr->Port(p.port(), ::TransportProto::TRANSPORT_TCP);
|
||||||
|
@ -657,7 +664,7 @@ inline ValPtr to_val(const hilti::rt::Port& p, const TypePtr& target) {
|
||||||
*/
|
*/
|
||||||
inline ValPtr to_val(const hilti::rt::Interval& i, const TypePtr& target) {
|
inline ValPtr to_val(const hilti::rt::Interval& i, const TypePtr& target) {
|
||||||
if ( target->Tag() != TYPE_INTERVAL )
|
if ( target->Tag() != TYPE_INTERVAL )
|
||||||
throw TypeMismatch("interval", target);
|
throw ParameterMismatch("interval", target);
|
||||||
|
|
||||||
return make_intrusive<IntervalVal>(i.seconds());
|
return make_intrusive<IntervalVal>(i.seconds());
|
||||||
}
|
}
|
||||||
|
@ -668,7 +675,7 @@ inline ValPtr to_val(const hilti::rt::Interval& i, const TypePtr& target) {
|
||||||
*/
|
*/
|
||||||
inline ValPtr to_val(const hilti::rt::Time& t, const TypePtr& target) {
|
inline ValPtr to_val(const hilti::rt::Time& t, const TypePtr& target) {
|
||||||
if ( target->Tag() != TYPE_TIME )
|
if ( target->Tag() != TYPE_TIME )
|
||||||
throw TypeMismatch("time", target);
|
throw ParameterMismatch("time", target);
|
||||||
|
|
||||||
return make_intrusive<TimeVal>(t.seconds());
|
return make_intrusive<TimeVal>(t.seconds());
|
||||||
}
|
}
|
||||||
|
@ -680,7 +687,7 @@ inline ValPtr to_val(const hilti::rt::Time& t, const TypePtr& target) {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline ValPtr to_val(const hilti::rt::Vector<T>& v, const TypePtr& target) {
|
inline ValPtr to_val(const hilti::rt::Vector<T>& v, const TypePtr& target) {
|
||||||
if ( target->Tag() != TYPE_VECTOR && target->Tag() != TYPE_LIST )
|
if ( target->Tag() != TYPE_VECTOR && target->Tag() != TYPE_LIST )
|
||||||
throw TypeMismatch("expected vector or list", target);
|
throw ParameterMismatch("expected vector or list", target);
|
||||||
|
|
||||||
auto vt = cast_intrusive<VectorType>(target);
|
auto vt = cast_intrusive<VectorType>(target);
|
||||||
auto zv = make_intrusive<VectorVal>(vt);
|
auto zv = make_intrusive<VectorVal>(vt);
|
||||||
|
@ -697,17 +704,17 @@ inline ValPtr to_val(const hilti::rt::Vector<T>& v, const TypePtr& target) {
|
||||||
template<typename K, typename V>
|
template<typename K, typename V>
|
||||||
inline ValPtr to_val(const hilti::rt::Map<K, V>& m, const TypePtr& target) {
|
inline ValPtr to_val(const hilti::rt::Map<K, V>& m, const TypePtr& target) {
|
||||||
if constexpr ( hilti::rt::is_tuple<K>::value )
|
if constexpr ( hilti::rt::is_tuple<K>::value )
|
||||||
throw TypeMismatch("internal error: sets with tuples not yet supported in to_val()");
|
throw ParameterMismatch("internal error: sets with tuples not yet supported in to_val()");
|
||||||
|
|
||||||
if ( target->Tag() != TYPE_TABLE )
|
if ( target->Tag() != TYPE_TABLE )
|
||||||
throw TypeMismatch("map", target);
|
throw ParameterMismatch("map", target);
|
||||||
|
|
||||||
auto tt = cast_intrusive<TableType>(target);
|
auto tt = cast_intrusive<TableType>(target);
|
||||||
if ( tt->IsSet() )
|
if ( tt->IsSet() )
|
||||||
throw TypeMismatch("map", target);
|
throw ParameterMismatch("map", target);
|
||||||
|
|
||||||
if ( tt->GetIndexTypes().size() != 1 )
|
if ( tt->GetIndexTypes().size() != 1 )
|
||||||
throw TypeMismatch("map with non-tuple elements", target);
|
throw ParameterMismatch("map with non-tuple elements", target);
|
||||||
|
|
||||||
auto zv = make_intrusive<TableVal>(tt);
|
auto zv = make_intrusive<TableVal>(tt);
|
||||||
|
|
||||||
|
@ -727,20 +734,20 @@ inline ValPtr to_val(const hilti::rt::Map<K, V>& m, const TypePtr& target) {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline ValPtr to_val(const hilti::rt::Set<T>& s, const TypePtr& target) {
|
inline ValPtr to_val(const hilti::rt::Set<T>& s, const TypePtr& target) {
|
||||||
if ( target->Tag() != TYPE_TABLE )
|
if ( target->Tag() != TYPE_TABLE )
|
||||||
throw TypeMismatch("set", target);
|
throw ParameterMismatch("set", target);
|
||||||
|
|
||||||
auto tt = cast_intrusive<TableType>(target);
|
auto tt = cast_intrusive<TableType>(target);
|
||||||
if ( ! tt->IsSet() )
|
if ( ! tt->IsSet() )
|
||||||
throw TypeMismatch("set", target);
|
throw ParameterMismatch("set", target);
|
||||||
|
|
||||||
auto zv = make_intrusive<TableVal>(tt);
|
auto zv = make_intrusive<TableVal>(tt);
|
||||||
|
|
||||||
for ( const auto& i : s ) {
|
for ( const auto& i : s ) {
|
||||||
if constexpr ( hilti::rt::is_tuple<T>::value )
|
if constexpr ( hilti::rt::is_tuple<T>::value )
|
||||||
throw TypeMismatch("internal error: sets with tuples not yet supported in to_val()");
|
throw ParameterMismatch("internal error: sets with tuples not yet supported in to_val()");
|
||||||
else {
|
else {
|
||||||
if ( tt->GetIndexTypes().size() != 1 )
|
if ( tt->GetIndexTypes().size() != 1 )
|
||||||
throw TypeMismatch("set with non-tuple elements", target);
|
throw ParameterMismatch("set with non-tuple elements", target);
|
||||||
|
|
||||||
auto idx = to_val(i, tt->GetIndexTypes()[0]);
|
auto idx = to_val(i, tt->GetIndexTypes()[0]);
|
||||||
zv->Assign(std::move(idx), nullptr);
|
zv->Assign(std::move(idx), nullptr);
|
||||||
|
@ -821,7 +828,7 @@ inline void set_record_field(RecordVal* rval, const IntrusivePtr<RecordType>& rt
|
||||||
// Field must be &optional or &default.
|
// Field must be &optional or &default.
|
||||||
if ( auto attrs = rtype->FieldDecl(idx)->attrs;
|
if ( auto attrs = rtype->FieldDecl(idx)->attrs;
|
||||||
! attrs || ! (attrs->Find(detail::ATTR_DEFAULT) || attrs->Find(detail::ATTR_OPTIONAL)) )
|
! attrs || ! (attrs->Find(detail::ATTR_DEFAULT) || attrs->Find(detail::ATTR_OPTIONAL)) )
|
||||||
throw TypeMismatch(hilti::rt::fmt("missing initialization for field '%s'", rtype->FieldName(idx)));
|
throw ParameterMismatch(hilti::rt::fmt("missing initialization for field '%s'", rtype->FieldName(idx)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -833,12 +840,12 @@ inline void set_record_field(RecordVal* rval, const IntrusivePtr<RecordType>& rt
|
||||||
template<typename T, typename std::enable_if_t<hilti::rt::is_tuple<T>::value>*>
|
template<typename T, typename std::enable_if_t<hilti::rt::is_tuple<T>::value>*>
|
||||||
inline ValPtr to_val(const T& t, const TypePtr& target) {
|
inline ValPtr to_val(const T& t, const TypePtr& target) {
|
||||||
if ( target->Tag() != TYPE_RECORD )
|
if ( target->Tag() != TYPE_RECORD )
|
||||||
throw TypeMismatch("tuple", target);
|
throw ParameterMismatch("tuple", target);
|
||||||
|
|
||||||
auto rtype = cast_intrusive<RecordType>(target);
|
auto rtype = cast_intrusive<RecordType>(target);
|
||||||
|
|
||||||
if ( std::tuple_size<T>::value != rtype->NumFields() )
|
if ( std::tuple_size<T>::value != rtype->NumFields() )
|
||||||
throw TypeMismatch("tuple", target);
|
throw ParameterMismatch("tuple", target);
|
||||||
|
|
||||||
auto rval = make_intrusive<RecordVal>(rtype);
|
auto rval = make_intrusive<RecordVal>(rtype);
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
|
@ -856,12 +863,12 @@ inline ValPtr to_val(const hilti::rt::Bitfield<Ts...>& v, const TypePtr& target)
|
||||||
using Bitfield = hilti::rt::Bitfield<Ts...>;
|
using Bitfield = hilti::rt::Bitfield<Ts...>;
|
||||||
|
|
||||||
if ( target->Tag() != TYPE_RECORD )
|
if ( target->Tag() != TYPE_RECORD )
|
||||||
throw TypeMismatch("bitfield", target);
|
throw ParameterMismatch("bitfield", target);
|
||||||
|
|
||||||
auto rtype = cast_intrusive<RecordType>(target);
|
auto rtype = cast_intrusive<RecordType>(target);
|
||||||
|
|
||||||
if ( sizeof...(Ts) - 1 != rtype->NumFields() )
|
if ( sizeof...(Ts) - 1 != rtype->NumFields() )
|
||||||
throw TypeMismatch("bitfield", target);
|
throw ParameterMismatch("bitfield", target);
|
||||||
|
|
||||||
auto rval = make_intrusive<RecordVal>(rtype);
|
auto rval = make_intrusive<RecordVal>(rtype);
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
|
@ -887,7 +894,7 @@ constexpr bool is_optional = is_optional_impl<std::remove_cv_t<std::remove_refer
|
||||||
template<typename T, typename std::enable_if_t<std::is_base_of<::hilti::rt::trait::isStruct, T>::value>*>
|
template<typename T, typename std::enable_if_t<std::is_base_of<::hilti::rt::trait::isStruct, T>::value>*>
|
||||||
inline ValPtr to_val(const T& t, const TypePtr& target) {
|
inline ValPtr to_val(const T& t, const TypePtr& target) {
|
||||||
if ( target->Tag() != TYPE_RECORD )
|
if ( target->Tag() != TYPE_RECORD )
|
||||||
throw TypeMismatch("struct", target);
|
throw ParameterMismatch("struct", target);
|
||||||
|
|
||||||
auto rtype = cast_intrusive<RecordType>(target);
|
auto rtype = cast_intrusive<RecordType>(target);
|
||||||
|
|
||||||
|
@ -898,7 +905,7 @@ inline ValPtr to_val(const T& t, const TypePtr& target) {
|
||||||
|
|
||||||
t.__visit([&](std::string_view name, const auto& val) {
|
t.__visit([&](std::string_view name, const auto& val) {
|
||||||
if ( idx >= num_fields )
|
if ( idx >= num_fields )
|
||||||
throw TypeMismatch(hilti::rt::fmt("no matching record field for field '%s'", name));
|
throw ParameterMismatch(hilti::rt::fmt("no matching record field for field '%s'", name));
|
||||||
|
|
||||||
// Special-case: Lift up anonymous bitfields (which always come as std::optionals).
|
// Special-case: Lift up anonymous bitfields (which always come as std::optionals).
|
||||||
if ( name == "<anon>" ) {
|
if ( name == "<anon>" ) {
|
||||||
|
@ -924,7 +931,7 @@ inline ValPtr to_val(const T& t, const TypePtr& target) {
|
||||||
std::string field_name = rtype->FieldName(idx);
|
std::string field_name = rtype->FieldName(idx);
|
||||||
|
|
||||||
if ( field_name != name )
|
if ( field_name != name )
|
||||||
throw TypeMismatch(
|
throw ParameterMismatch(
|
||||||
hilti::rt::fmt("mismatch in field name: expected '%s', found '%s'", name, field_name));
|
hilti::rt::fmt("mismatch in field name: expected '%s', found '%s'", name, field_name));
|
||||||
|
|
||||||
set_record_field(rval.get(), rtype, idx++, val);
|
set_record_field(rval.get(), rtype, idx++, val);
|
||||||
|
@ -934,7 +941,7 @@ inline ValPtr to_val(const T& t, const TypePtr& target) {
|
||||||
// We already check above that all Spicy-side fields are mapped so we
|
// We already check above that all Spicy-side fields are mapped so we
|
||||||
// can only hit this if there are uninitialized Zeek-side fields left.
|
// can only hit this if there are uninitialized Zeek-side fields left.
|
||||||
if ( idx != num_fields )
|
if ( idx != num_fields )
|
||||||
throw TypeMismatch(hilti::rt::fmt("missing initialization for field '%s'", rtype->FieldName(idx + 1)));
|
throw ParameterMismatch(hilti::rt::fmt("missing initialization for field '%s'", rtype->FieldName(idx + 1)));
|
||||||
|
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
@ -959,7 +966,7 @@ inline ValPtr to_val_for_transport_proto(int64_t val, const TypePtr& target) {
|
||||||
template<typename T, typename std::enable_if_t<std::is_enum<typename T::Value>::value>*>
|
template<typename T, typename std::enable_if_t<std::is_enum<typename T::Value>::value>*>
|
||||||
inline ValPtr to_val(const T& t, const TypePtr& target) {
|
inline ValPtr to_val(const T& t, const TypePtr& target) {
|
||||||
if ( target->Tag() != TYPE_ENUM )
|
if ( target->Tag() != TYPE_ENUM )
|
||||||
throw TypeMismatch("enum", target);
|
throw ParameterMismatch("enum", target);
|
||||||
|
|
||||||
// We'll usually be getting an int64_t for T, but allow other signed ints
|
// We'll usually be getting an int64_t for T, but allow other signed ints
|
||||||
// as well.
|
// as well.
|
||||||
|
@ -969,7 +976,7 @@ inline ValPtr to_val(const T& t, const TypePtr& target) {
|
||||||
// Special case: map enum values to Zeek's semantics.
|
// Special case: map enum values to Zeek's semantics.
|
||||||
if ( target->GetName() == "transport_proto" ) {
|
if ( target->GetName() == "transport_proto" ) {
|
||||||
if ( ! std::is_same_v<T, hilti::rt::Protocol> )
|
if ( ! std::is_same_v<T, hilti::rt::Protocol> )
|
||||||
throw TypeMismatch(hilti::rt::demangle(typeid(t).name()), target);
|
throw ParameterMismatch(hilti::rt::demangle(typeid(t).name()), target);
|
||||||
|
|
||||||
return to_val_for_transport_proto(it, target);
|
return to_val_for_transport_proto(it, target);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue