22
33#include < cstring>
44
5+ #include " cbor/schema.hpp"
56#include " cbor/strict.hpp"
67
78namespace VMPilot ::Cbor {
@@ -10,6 +11,9 @@ struct CborConsumerTraits<VMPilot::Runtime::EH::ContractParseError> {
1011 using E = VMPilot::Runtime::EH::ContractParseError;
1112 static constexpr E missing_field = E::MissingField;
1213 static constexpr E wrong_field_type = E::WrongFieldType;
14+ static constexpr E bad_cbor = E::BadCbor;
15+ static constexpr E not_a_map = E::NotAMap;
16+ static constexpr E unknown_enum_value = E::UnknownEnumValue;
1317};
1418} // namespace VMPilot::Cbor
1519
@@ -71,50 +75,6 @@ require_map_field(const Value& map,
7175 return value;
7276}
7377
74- tl::expected<ExecutableEhStatus, ContractParseError>
75- parse_executable_eh_status (std::string_view text) noexcept {
76- if (text == " reserved_disabled_v1" ) {
77- return ExecutableEhStatus::ReservedDisabledV1;
78- }
79- if (text == " executable_v1_1" ) {
80- return ExecutableEhStatus::ExecutableV1_1;
81- }
82- return parse_err (ContractParseError::UnknownEnumValue);
83- }
84-
85- tl::expected<CrossProtectedFrameUnwind, ContractParseError>
86- parse_cross_protected_frame_unwind (std::string_view text) noexcept {
87- if (text == " forbidden" ) {
88- return CrossProtectedFrameUnwind::Forbidden;
89- }
90- if (text == " permitted_by_profile" ) {
91- return CrossProtectedFrameUnwind::PermittedByProfile;
92- }
93- return parse_err (ContractParseError::UnknownEnumValue);
94- }
95-
96- tl::expected<NativeBoundaryUnwindBehavior, ContractParseError>
97- parse_native_boundary_unwind_behavior (std::string_view text) noexcept {
98- if (text == " translate_to_trap_or_fail_closed" ) {
99- return NativeBoundaryUnwindBehavior::TranslateToTrapOrFailClosed;
100- }
101- if (text == " profile-upgraded" ) {
102- return NativeBoundaryUnwindBehavior::ProfileUpgraded;
103- }
104- return parse_err (ContractParseError::UnknownEnumValue);
105- }
106-
107- tl::expected<ReservedTableStatus, ContractParseError>
108- parse_reserved_table_status (std::string_view text) noexcept {
109- if (text == " reserved_empty" ) {
110- return ReservedTableStatus::ReservedEmpty;
111- }
112- if (text == " profile-specific" ) {
113- return ReservedTableStatus::ProfileSpecific;
114- }
115- return parse_err (ContractParseError::UnknownEnumValue);
116- }
117-
11878bool contract_has_unknown_extension (const Value& map) noexcept {
11979 for (std::size_t index = 0 ; index < map.map_size (); ++index) {
12080 const Value& key = map.map_key_at (index);
@@ -324,91 +284,60 @@ parse_exception_unwind_contract(const std::uint8_t* data,
324284 return parse_err (ContractParseError::UnknownCriticalExtension);
325285 }
326286
327- auto eh_contract_version = require_text (contract, kEh_EhContractVersion );
328- auto executable_eh_status_text =
329- require_text (contract, kEh_ExecutableEhStatus );
330- auto planned_executable_eh_epoch =
331- require_text (contract, kEh_PlannedExecutableEhEpoch );
332- auto cross_protected_frame_unwind_text =
333- require_text (contract, kEh_CrossProtectedFrameUnwind );
334- auto native_boundary_unwind_behavior_text =
335- require_text (contract, kEh_NativeBoundaryUnwindBehavior );
336- auto handler_table_status_text =
337- require_text (contract, kEh_HandlerTableStatus );
338- auto cleanup_table_status_text =
339- require_text (contract, kEh_CleanupTableStatus );
340- auto frame_contract_ref = require_text (contract, kEh_FrameContractRef );
341- auto stackmap_contract_ref = require_text (contract, kEh_StackmapContractRef );
342- auto resume_contract_ref = require_text (contract, kEh_ResumeContractRef );
343- auto verifier_rules_ref = require_text (contract, kEh_VerifierRulesRef );
344- auto family_specific_unwind_surface_ref =
345- require_text (contract, kEh_FamilySpecificUnwindSurfaceRef );
346-
347- if (!eh_contract_version) return parse_err (eh_contract_version.error ());
348- if (!executable_eh_status_text) {
349- return parse_err (executable_eh_status_text.error ());
350- }
351- if (!planned_executable_eh_epoch) {
352- return parse_err (planned_executable_eh_epoch.error ());
353- }
354- if (!cross_protected_frame_unwind_text) {
355- return parse_err (cross_protected_frame_unwind_text.error ());
356- }
357- if (!native_boundary_unwind_behavior_text) {
358- return parse_err (native_boundary_unwind_behavior_text.error ());
359- }
360- if (!handler_table_status_text) {
361- return parse_err (handler_table_status_text.error ());
362- }
363- if (!cleanup_table_status_text) {
364- return parse_err (cleanup_table_status_text.error ());
365- }
366- if (!frame_contract_ref) return parse_err (frame_contract_ref.error ());
367- if (!stackmap_contract_ref) return parse_err (stackmap_contract_ref.error ());
368- if (!resume_contract_ref) return parse_err (resume_contract_ref.error ());
369- if (!verifier_rules_ref) return parse_err (verifier_rules_ref.error ());
370- if (!family_specific_unwind_surface_ref) {
371- return parse_err (family_specific_unwind_surface_ref.error ());
372- }
373-
374- auto executable_eh_status =
375- parse_executable_eh_status (*executable_eh_status_text);
376- auto cross_protected_frame_unwind =
377- parse_cross_protected_frame_unwind (*cross_protected_frame_unwind_text);
378- auto native_boundary_unwind_behavior =
379- parse_native_boundary_unwind_behavior (
380- *native_boundary_unwind_behavior_text);
381- auto handler_table_status =
382- parse_reserved_table_status (*handler_table_status_text);
383- auto cleanup_table_status =
384- parse_reserved_table_status (*cleanup_table_status_text);
385-
386- if (!executable_eh_status) return parse_err (executable_eh_status.error ());
387- if (!cross_protected_frame_unwind) {
388- return parse_err (cross_protected_frame_unwind.error ());
389- }
390- if (!native_boundary_unwind_behavior) {
391- return parse_err (native_boundary_unwind_behavior.error ());
392- }
393- if (!handler_table_status) return parse_err (handler_table_status.error ());
394- if (!cleanup_table_status) return parse_err (cleanup_table_status.error ());
395-
396- ExceptionUnwindContract out;
397- out.semantic_contract_version = std::move (*semantic_contract_version);
398- out.eh_contract_version = std::move (*eh_contract_version);
399- out.executable_eh_status = *executable_eh_status;
400- out.planned_executable_eh_epoch = std::move (*planned_executable_eh_epoch);
401- out.cross_protected_frame_unwind = *cross_protected_frame_unwind;
402- out.native_boundary_unwind_behavior = *native_boundary_unwind_behavior;
403- out.handler_table_status = *handler_table_status;
404- out.cleanup_table_status = *cleanup_table_status;
405- out.frame_contract_ref = std::move (*frame_contract_ref);
406- out.stackmap_contract_ref = std::move (*stackmap_contract_ref);
407- out.resume_contract_ref = std::move (*resume_contract_ref);
408- out.verifier_rules_ref = std::move (*verifier_rules_ref);
409- out.family_specific_unwind_surface_ref =
410- std::move (*family_specific_unwind_surface_ref);
411- return out;
287+ using namespace VMPilot ::Cbor::Schema;
288+ const auto schema = std::make_tuple (
289+ TextField<ExceptionUnwindContract>{
290+ kEh_EhContractVersion ,
291+ &ExceptionUnwindContract::eh_contract_version},
292+ EnumTextField<ExceptionUnwindContract, ExecutableEhStatus,
293+ ContractParseError>{
294+ kEh_ExecutableEhStatus ,
295+ &ExceptionUnwindContract::executable_eh_status,
296+ ContractParseError::UnknownEnumValue},
297+ TextField<ExceptionUnwindContract>{
298+ kEh_PlannedExecutableEhEpoch ,
299+ &ExceptionUnwindContract::planned_executable_eh_epoch},
300+ EnumTextField<ExceptionUnwindContract, CrossProtectedFrameUnwind,
301+ ContractParseError>{
302+ kEh_CrossProtectedFrameUnwind ,
303+ &ExceptionUnwindContract::cross_protected_frame_unwind,
304+ ContractParseError::UnknownEnumValue},
305+ EnumTextField<ExceptionUnwindContract, NativeBoundaryUnwindBehavior,
306+ ContractParseError>{
307+ kEh_NativeBoundaryUnwindBehavior ,
308+ &ExceptionUnwindContract::native_boundary_unwind_behavior,
309+ ContractParseError::UnknownEnumValue},
310+ EnumTextField<ExceptionUnwindContract, ReservedTableStatus,
311+ ContractParseError>{
312+ kEh_HandlerTableStatus ,
313+ &ExceptionUnwindContract::handler_table_status,
314+ ContractParseError::UnknownEnumValue},
315+ EnumTextField<ExceptionUnwindContract, ReservedTableStatus,
316+ ContractParseError>{
317+ kEh_CleanupTableStatus ,
318+ &ExceptionUnwindContract::cleanup_table_status,
319+ ContractParseError::UnknownEnumValue},
320+ TextField<ExceptionUnwindContract>{
321+ kEh_FrameContractRef ,
322+ &ExceptionUnwindContract::frame_contract_ref},
323+ TextField<ExceptionUnwindContract>{
324+ kEh_StackmapContractRef ,
325+ &ExceptionUnwindContract::stackmap_contract_ref},
326+ TextField<ExceptionUnwindContract>{
327+ kEh_ResumeContractRef ,
328+ &ExceptionUnwindContract::resume_contract_ref},
329+ TextField<ExceptionUnwindContract>{
330+ kEh_VerifierRulesRef ,
331+ &ExceptionUnwindContract::verifier_rules_ref},
332+ TextField<ExceptionUnwindContract>{
333+ kEh_FamilySpecificUnwindSurfaceRef ,
334+ &ExceptionUnwindContract::family_specific_unwind_surface_ref}
335+ );
336+ auto parsed =
337+ parse_schema<ExceptionUnwindContract, ContractParseError>(contract, schema);
338+ if (!parsed) return parse_err (parsed.error ());
339+ parsed->semantic_contract_version = std::move (*semantic_contract_version);
340+ return parsed;
412341}
413342
414343tl::expected<ExceptionUnwindContract, ContractVerifyError>
0 commit comments