diff --git a/src/struct_frame/boilerplate/c/basic_default.h b/src/struct_frame/boilerplate/c/basic_default.h index 7d7c415d..b9be7a02 100644 --- a/src/struct_frame/boilerplate/c/basic_default.h +++ b/src/struct_frame/boilerplate/c/basic_default.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/basic_extended.h b/src/struct_frame/boilerplate/c/basic_extended.h index 56136f98..f48a8182 100644 --- a/src/struct_frame/boilerplate/c/basic_extended.h +++ b/src/struct_frame/boilerplate/c/basic_extended.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/basic_extended_length.h b/src/struct_frame/boilerplate/c/basic_extended_length.h index 8022954f..3fe8d42e 100644 --- a/src/struct_frame/boilerplate/c/basic_extended_length.h +++ b/src/struct_frame/boilerplate/c/basic_extended_length.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/basic_extended_msg_ids.h b/src/struct_frame/boilerplate/c/basic_extended_msg_ids.h index cbb223b8..b51fcc5b 100644 --- a/src/struct_frame/boilerplate/c/basic_extended_msg_ids.h +++ b/src/struct_frame/boilerplate/c/basic_extended_msg_ids.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/basic_extended_multi_system_stream.h b/src/struct_frame/boilerplate/c/basic_extended_multi_system_stream.h index 14fbc1c9..d6ccf9db 100644 --- a/src/struct_frame/boilerplate/c/basic_extended_multi_system_stream.h +++ b/src/struct_frame/boilerplate/c/basic_extended_multi_system_stream.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/basic_minimal.h b/src/struct_frame/boilerplate/c/basic_minimal.h index abded682..dae08c80 100644 --- a/src/struct_frame/boilerplate/c/basic_minimal.h +++ b/src/struct_frame/boilerplate/c/basic_minimal.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/basic_multi_system_stream.h b/src/struct_frame/boilerplate/c/basic_multi_system_stream.h index f124f497..4a99c861 100644 --- a/src/struct_frame/boilerplate/c/basic_multi_system_stream.h +++ b/src/struct_frame/boilerplate/c/basic_multi_system_stream.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/basic_seq.h b/src/struct_frame/boilerplate/c/basic_seq.h index d2cbc063..bd1d55f3 100644 --- a/src/struct_frame/boilerplate/c/basic_seq.h +++ b/src/struct_frame/boilerplate/c/basic_seq.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/basic_sys_comp.h b/src/struct_frame/boilerplate/c/basic_sys_comp.h index c15aa6b4..d2559d82 100644 --- a/src/struct_frame/boilerplate/c/basic_sys_comp.h +++ b/src/struct_frame/boilerplate/c/basic_sys_comp.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/frame_base.h b/src/struct_frame/boilerplate/c/frame_base.h index e72d9620..729d618c 100644 --- a/src/struct_frame/boilerplate/c/frame_base.h +++ b/src/struct_frame/boilerplate/c/frame_base.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser base utilities */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/frame_format_config.h b/src/struct_frame/boilerplate/c/frame_format_config.h index 170e7b39..63dae554 100644 --- a/src/struct_frame/boilerplate/c/frame_format_config.h +++ b/src/struct_frame/boilerplate/c/frame_format_config.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/frame_parsers.h b/src/struct_frame/boilerplate/c/frame_parsers.h index 72057973..0469ffd6 100644 --- a/src/struct_frame/boilerplate/c/frame_parsers.h +++ b/src/struct_frame/boilerplate/c/frame_parsers.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser main header */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/mavlink_v1_frame.h b/src/struct_frame/boilerplate/c/mavlink_v1_frame.h index 0c9a705c..a9d36fad 100644 --- a/src/struct_frame/boilerplate/c/mavlink_v1_frame.h +++ b/src/struct_frame/boilerplate/c/mavlink_v1_frame.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/mavlink_v2_frame.h b/src/struct_frame/boilerplate/c/mavlink_v2_frame.h index 745ed1f8..e4732c45 100644 --- a/src/struct_frame/boilerplate/c/mavlink_v2_frame.h +++ b/src/struct_frame/boilerplate/c/mavlink_v2_frame.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/tiny_default.h b/src/struct_frame/boilerplate/c/tiny_default.h index 9c285171..9ab9f0b8 100644 --- a/src/struct_frame/boilerplate/c/tiny_default.h +++ b/src/struct_frame/boilerplate/c/tiny_default.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/tiny_extended.h b/src/struct_frame/boilerplate/c/tiny_extended.h index b1031168..7284c2fb 100644 --- a/src/struct_frame/boilerplate/c/tiny_extended.h +++ b/src/struct_frame/boilerplate/c/tiny_extended.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/tiny_extended_length.h b/src/struct_frame/boilerplate/c/tiny_extended_length.h index fd3fcd75..b2fa1893 100644 --- a/src/struct_frame/boilerplate/c/tiny_extended_length.h +++ b/src/struct_frame/boilerplate/c/tiny_extended_length.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/tiny_extended_msg_ids.h b/src/struct_frame/boilerplate/c/tiny_extended_msg_ids.h index 3dfb96c4..c05f2814 100644 --- a/src/struct_frame/boilerplate/c/tiny_extended_msg_ids.h +++ b/src/struct_frame/boilerplate/c/tiny_extended_msg_ids.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/tiny_extended_multi_system_stream.h b/src/struct_frame/boilerplate/c/tiny_extended_multi_system_stream.h index 614686aa..9ce03404 100644 --- a/src/struct_frame/boilerplate/c/tiny_extended_multi_system_stream.h +++ b/src/struct_frame/boilerplate/c/tiny_extended_multi_system_stream.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/tiny_minimal.h b/src/struct_frame/boilerplate/c/tiny_minimal.h index 87889260..85b0b1ce 100644 --- a/src/struct_frame/boilerplate/c/tiny_minimal.h +++ b/src/struct_frame/boilerplate/c/tiny_minimal.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/tiny_multi_system_stream.h b/src/struct_frame/boilerplate/c/tiny_multi_system_stream.h index 9a062559..6787665c 100644 --- a/src/struct_frame/boilerplate/c/tiny_multi_system_stream.h +++ b/src/struct_frame/boilerplate/c/tiny_multi_system_stream.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/tiny_seq.h b/src/struct_frame/boilerplate/c/tiny_seq.h index 1560dc53..cd71b2b1 100644 --- a/src/struct_frame/boilerplate/c/tiny_seq.h +++ b/src/struct_frame/boilerplate/c/tiny_seq.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/tiny_sys_comp.h b/src/struct_frame/boilerplate/c/tiny_sys_comp.h index bfd85ddb..76d55cb6 100644 --- a/src/struct_frame/boilerplate/c/tiny_sys_comp.h +++ b/src/struct_frame/boilerplate/c/tiny_sys_comp.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/c/ubx_frame.h b/src/struct_frame/boilerplate/c/ubx_frame.h index 0cdb6ffe..a11b7e1d 100644 --- a/src/struct_frame/boilerplate/c/ubx_frame.h +++ b/src/struct_frame/boilerplate/c/ubx_frame.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/BasicDefault.hpp b/src/struct_frame/boilerplate/cpp/BasicDefault.hpp index 25ffd1fc..5efc0ba6 100644 --- a/src/struct_frame/boilerplate/cpp/BasicDefault.hpp +++ b/src/struct_frame/boilerplate/cpp/BasicDefault.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/BasicExtended.hpp b/src/struct_frame/boilerplate/cpp/BasicExtended.hpp index 2cb6c011..86996959 100644 --- a/src/struct_frame/boilerplate/cpp/BasicExtended.hpp +++ b/src/struct_frame/boilerplate/cpp/BasicExtended.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/BasicExtendedLength.hpp b/src/struct_frame/boilerplate/cpp/BasicExtendedLength.hpp index a3f4b9e4..71571bd2 100644 --- a/src/struct_frame/boilerplate/cpp/BasicExtendedLength.hpp +++ b/src/struct_frame/boilerplate/cpp/BasicExtendedLength.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/BasicExtendedMsgIds.hpp b/src/struct_frame/boilerplate/cpp/BasicExtendedMsgIds.hpp index 2258bcb7..f60787d9 100644 --- a/src/struct_frame/boilerplate/cpp/BasicExtendedMsgIds.hpp +++ b/src/struct_frame/boilerplate/cpp/BasicExtendedMsgIds.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/BasicExtendedMultiSystemStream.hpp b/src/struct_frame/boilerplate/cpp/BasicExtendedMultiSystemStream.hpp index 3f7dd650..dec5924f 100644 --- a/src/struct_frame/boilerplate/cpp/BasicExtendedMultiSystemStream.hpp +++ b/src/struct_frame/boilerplate/cpp/BasicExtendedMultiSystemStream.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/BasicMinimal.hpp b/src/struct_frame/boilerplate/cpp/BasicMinimal.hpp index 31155290..fca39b89 100644 --- a/src/struct_frame/boilerplate/cpp/BasicMinimal.hpp +++ b/src/struct_frame/boilerplate/cpp/BasicMinimal.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/BasicMultiSystemStream.hpp b/src/struct_frame/boilerplate/cpp/BasicMultiSystemStream.hpp index b4b1e20c..5104d52d 100644 --- a/src/struct_frame/boilerplate/cpp/BasicMultiSystemStream.hpp +++ b/src/struct_frame/boilerplate/cpp/BasicMultiSystemStream.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/BasicSeq.hpp b/src/struct_frame/boilerplate/cpp/BasicSeq.hpp index 4a64f4eb..8c5d9842 100644 --- a/src/struct_frame/boilerplate/cpp/BasicSeq.hpp +++ b/src/struct_frame/boilerplate/cpp/BasicSeq.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/BasicSysComp.hpp b/src/struct_frame/boilerplate/cpp/BasicSysComp.hpp index ab5a3423..7009478c 100644 --- a/src/struct_frame/boilerplate/cpp/BasicSysComp.hpp +++ b/src/struct_frame/boilerplate/cpp/BasicSysComp.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/FrameFormatConfig.hpp b/src/struct_frame/boilerplate/cpp/FrameFormatConfig.hpp index 18ae3e35..43190d44 100644 --- a/src/struct_frame/boilerplate/cpp/FrameFormatConfig.hpp +++ b/src/struct_frame/boilerplate/cpp/FrameFormatConfig.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/MavlinkV1Frame.hpp b/src/struct_frame/boilerplate/cpp/MavlinkV1Frame.hpp index af21dc5c..32563371 100644 --- a/src/struct_frame/boilerplate/cpp/MavlinkV1Frame.hpp +++ b/src/struct_frame/boilerplate/cpp/MavlinkV1Frame.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/MavlinkV2Frame.hpp b/src/struct_frame/boilerplate/cpp/MavlinkV2Frame.hpp index d3d54d3f..b36003a3 100644 --- a/src/struct_frame/boilerplate/cpp/MavlinkV2Frame.hpp +++ b/src/struct_frame/boilerplate/cpp/MavlinkV2Frame.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/TinyDefault.hpp b/src/struct_frame/boilerplate/cpp/TinyDefault.hpp index bdfda580..2fb609e6 100644 --- a/src/struct_frame/boilerplate/cpp/TinyDefault.hpp +++ b/src/struct_frame/boilerplate/cpp/TinyDefault.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/TinyExtended.hpp b/src/struct_frame/boilerplate/cpp/TinyExtended.hpp index 61ffbacc..6d70497f 100644 --- a/src/struct_frame/boilerplate/cpp/TinyExtended.hpp +++ b/src/struct_frame/boilerplate/cpp/TinyExtended.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/TinyExtendedLength.hpp b/src/struct_frame/boilerplate/cpp/TinyExtendedLength.hpp index da933088..37d5acc9 100644 --- a/src/struct_frame/boilerplate/cpp/TinyExtendedLength.hpp +++ b/src/struct_frame/boilerplate/cpp/TinyExtendedLength.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/TinyExtendedMsgIds.hpp b/src/struct_frame/boilerplate/cpp/TinyExtendedMsgIds.hpp index 0b89b0a8..3d32b6f8 100644 --- a/src/struct_frame/boilerplate/cpp/TinyExtendedMsgIds.hpp +++ b/src/struct_frame/boilerplate/cpp/TinyExtendedMsgIds.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/TinyExtendedMultiSystemStream.hpp b/src/struct_frame/boilerplate/cpp/TinyExtendedMultiSystemStream.hpp index 921ae626..df4b81a1 100644 --- a/src/struct_frame/boilerplate/cpp/TinyExtendedMultiSystemStream.hpp +++ b/src/struct_frame/boilerplate/cpp/TinyExtendedMultiSystemStream.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/TinyMinimal.hpp b/src/struct_frame/boilerplate/cpp/TinyMinimal.hpp index d27c0078..e2cd4c5b 100644 --- a/src/struct_frame/boilerplate/cpp/TinyMinimal.hpp +++ b/src/struct_frame/boilerplate/cpp/TinyMinimal.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/TinyMultiSystemStream.hpp b/src/struct_frame/boilerplate/cpp/TinyMultiSystemStream.hpp index 017cc040..90f85688 100644 --- a/src/struct_frame/boilerplate/cpp/TinyMultiSystemStream.hpp +++ b/src/struct_frame/boilerplate/cpp/TinyMultiSystemStream.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/TinySeq.hpp b/src/struct_frame/boilerplate/cpp/TinySeq.hpp index 6d227b4a..8d4c6085 100644 --- a/src/struct_frame/boilerplate/cpp/TinySeq.hpp +++ b/src/struct_frame/boilerplate/cpp/TinySeq.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/TinySysComp.hpp b/src/struct_frame/boilerplate/cpp/TinySysComp.hpp index 17e0cec1..5b6d54a7 100644 --- a/src/struct_frame/boilerplate/cpp/TinySysComp.hpp +++ b/src/struct_frame/boilerplate/cpp/TinySysComp.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/UbxFrame.hpp b/src/struct_frame/boilerplate/cpp/UbxFrame.hpp index 1a76da38..cf7a580d 100644 --- a/src/struct_frame/boilerplate/cpp/UbxFrame.hpp +++ b/src/struct_frame/boilerplate/cpp/UbxFrame.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/frame_base.hpp b/src/struct_frame/boilerplate/cpp/frame_base.hpp index 8aa17db6..7c2b25a7 100644 --- a/src/struct_frame/boilerplate/cpp/frame_base.hpp +++ b/src/struct_frame/boilerplate/cpp/frame_base.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser base utilities */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/cpp/frame_parsers.hpp b/src/struct_frame/boilerplate/cpp/frame_parsers.hpp index 7909e702..38253a37 100644 --- a/src/struct_frame/boilerplate/cpp/frame_parsers.hpp +++ b/src/struct_frame/boilerplate/cpp/frame_parsers.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser main header */ -/* Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. */ #pragma once diff --git a/src/struct_frame/boilerplate/js/BasicDefault.js b/src/struct_frame/boilerplate/js/BasicDefault.js index ce0dbf20..ed27c71a 100644 --- a/src/struct_frame/boilerplate/js/BasicDefault.js +++ b/src/struct_frame/boilerplate/js/BasicDefault.js @@ -1,135 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// BasicDefault Frame Format +// BasicDefault Frame Format Configuration // ============================================================================= -const BasicDefaultParserState = { - LOOKING_FOR_START1: 0, - LOOKING_FOR_START2: 1, - GETTING_MSG_ID: 2, - GETTING_LENGTH: 3, - GETTING_PAYLOAD: 4 +/** Configuration for BasicDefault frame format */ +const BasicDefaultConfig = { + name: 'BasicDefault', + startBytes: [0x90, 0x71], + headerSize: 4, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, }; /** * BasicDefault - Frame format parser and encoder + * + * Format: [START_BYTE1=0x90] [START_BYTE2=0x71] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class BasicDefault { - static START_BYTE1 = 0x90; - static START_BYTE2 = 0x71; - static HEADER_SIZE = 4; - static FOOTER_SIZE = 2; - static OVERHEAD = 6; - static LENGTH_BYTES = 1; +const BasicDefault = createFrameParserClass(BasicDefaultConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = BasicDefaultParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - reset() { - this.state = BasicDefaultParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case BasicDefaultParserState.LOOKING_FOR_START1: - if (byte === BasicDefault.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicDefaultParserState.LOOKING_FOR_START2; - } - break; - - case BasicDefaultParserState.LOOKING_FOR_START2: - if (byte === BasicDefault.START_BYTE2) { - this.buffer.push(byte); - this.state = BasicDefaultParserState.GETTING_MSG_ID; - } else if (byte === BasicDefault.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicDefaultParserState.LOOKING_FOR_START2; - } else { - this.state = BasicDefaultParserState.LOOKING_FOR_START1; - } - break; - - case BasicDefaultParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = BasicDefaultParserState.GETTING_LENGTH; - break; - - case BasicDefaultParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = BasicDefault.OVERHEAD + this.msg_length; - this.state = BasicDefaultParserState.GETTING_PAYLOAD; - break; - - case BasicDefaultParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, BasicDefault.HEADER_SIZE, 1, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = BasicDefaultParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(BasicDefault.START_BYTE1); - output.push(BasicDefault.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 2); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < BasicDefault.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== BasicDefault.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== BasicDefault.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicDefault.HEADER_SIZE, 1, 2); - } -} +/** Parser state alias for backward compatibility */ +const BasicDefaultParserState = GenericParserState; module.exports = { BasicDefault, + BasicDefaultConfig, BasicDefaultParserState, }; diff --git a/src/struct_frame/boilerplate/js/BasicExtended.js b/src/struct_frame/boilerplate/js/BasicExtended.js index d161cc97..0a5f62c8 100644 --- a/src/struct_frame/boilerplate/js/BasicExtended.js +++ b/src/struct_frame/boilerplate/js/BasicExtended.js @@ -1,140 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// BasicExtended Frame Format +// BasicExtended Frame Format Configuration // ============================================================================= -const BasicExtendedParserState = { - LOOKING_FOR_START1: 0, - LOOKING_FOR_START2: 1, - GETTING_MSG_ID: 2, - GETTING_LENGTH: 3, - GETTING_PAYLOAD: 4 +/** Configuration for BasicExtended frame format */ +const BasicExtendedConfig = { + name: 'BasicExtended', + startBytes: [0x90, 0x74], + headerSize: 6, + footerSize: 2, + hasLength: true, + lengthBytes: 2, + hasCrc: true, }; /** * BasicExtended - Frame format parser and encoder + * + * Format: [START_BYTE1=0x90] [START_BYTE2=0x74] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class BasicExtended { - static START_BYTE1 = 0x90; - static START_BYTE2 = 0x74; - static HEADER_SIZE = 6; - static FOOTER_SIZE = 2; - static OVERHEAD = 8; - static LENGTH_BYTES = 2; +const BasicExtended = createFrameParserClass(BasicExtendedConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = BasicExtendedParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - this.length_lo = 0; - } - - reset() { - this.state = BasicExtendedParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case BasicExtendedParserState.LOOKING_FOR_START1: - if (byte === BasicExtended.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicExtendedParserState.LOOKING_FOR_START2; - } - break; - - case BasicExtendedParserState.LOOKING_FOR_START2: - if (byte === BasicExtended.START_BYTE2) { - this.buffer.push(byte); - this.state = BasicExtendedParserState.GETTING_MSG_ID; - } else if (byte === BasicExtended.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicExtendedParserState.LOOKING_FOR_START2; - } else { - this.state = BasicExtendedParserState.LOOKING_FOR_START1; - } - break; - - case BasicExtendedParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = BasicExtendedParserState.GETTING_LENGTH; - break; - - case BasicExtendedParserState.GETTING_LENGTH: - this.buffer.push(byte); - if (this.buffer.length === 4) { - this.length_lo = byte; - } else { - this.msg_length = this.length_lo | (byte << 8); - this.packet_size = BasicExtended.OVERHEAD + this.msg_length; - this.state = BasicExtendedParserState.GETTING_PAYLOAD; - } - break; - - case BasicExtendedParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, BasicExtended.HEADER_SIZE, 2, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = BasicExtendedParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(BasicExtended.START_BYTE1); - output.push(BasicExtended.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 2, 2); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < BasicExtended.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== BasicExtended.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== BasicExtended.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicExtended.HEADER_SIZE, 2, 2); - } -} +/** Parser state alias for backward compatibility */ +const BasicExtendedParserState = GenericParserState; module.exports = { BasicExtended, + BasicExtendedConfig, BasicExtendedParserState, }; diff --git a/src/struct_frame/boilerplate/js/BasicExtendedLength.js b/src/struct_frame/boilerplate/js/BasicExtendedLength.js index 9ddf0a43..6b85964b 100644 --- a/src/struct_frame/boilerplate/js/BasicExtendedLength.js +++ b/src/struct_frame/boilerplate/js/BasicExtendedLength.js @@ -1,140 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// BasicExtendedLength Frame Format +// BasicExtendedLength Frame Format Configuration // ============================================================================= -const BasicExtendedLengthParserState = { - LOOKING_FOR_START1: 0, - LOOKING_FOR_START2: 1, - GETTING_MSG_ID: 2, - GETTING_LENGTH: 3, - GETTING_PAYLOAD: 4 +/** Configuration for BasicExtendedLength frame format */ +const BasicExtendedLengthConfig = { + name: 'BasicExtendedLength', + startBytes: [0x90, 0x73], + headerSize: 5, + footerSize: 2, + hasLength: true, + lengthBytes: 2, + hasCrc: true, }; /** * BasicExtendedLength - Frame format parser and encoder + * + * Format: [START_BYTE1=0x90] [START_BYTE2=0x73] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class BasicExtendedLength { - static START_BYTE1 = 0x90; - static START_BYTE2 = 0x73; - static HEADER_SIZE = 5; - static FOOTER_SIZE = 2; - static OVERHEAD = 7; - static LENGTH_BYTES = 2; +const BasicExtendedLength = createFrameParserClass(BasicExtendedLengthConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = BasicExtendedLengthParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - this.length_lo = 0; - } - - reset() { - this.state = BasicExtendedLengthParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case BasicExtendedLengthParserState.LOOKING_FOR_START1: - if (byte === BasicExtendedLength.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicExtendedLengthParserState.LOOKING_FOR_START2; - } - break; - - case BasicExtendedLengthParserState.LOOKING_FOR_START2: - if (byte === BasicExtendedLength.START_BYTE2) { - this.buffer.push(byte); - this.state = BasicExtendedLengthParserState.GETTING_MSG_ID; - } else if (byte === BasicExtendedLength.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicExtendedLengthParserState.LOOKING_FOR_START2; - } else { - this.state = BasicExtendedLengthParserState.LOOKING_FOR_START1; - } - break; - - case BasicExtendedLengthParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = BasicExtendedLengthParserState.GETTING_LENGTH; - break; - - case BasicExtendedLengthParserState.GETTING_LENGTH: - this.buffer.push(byte); - if (this.buffer.length === 4) { - this.length_lo = byte; - } else { - this.msg_length = this.length_lo | (byte << 8); - this.packet_size = BasicExtendedLength.OVERHEAD + this.msg_length; - this.state = BasicExtendedLengthParserState.GETTING_PAYLOAD; - } - break; - - case BasicExtendedLengthParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, BasicExtendedLength.HEADER_SIZE, 2, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = BasicExtendedLengthParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(BasicExtendedLength.START_BYTE1); - output.push(BasicExtendedLength.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 2, 2); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < BasicExtendedLength.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== BasicExtendedLength.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== BasicExtendedLength.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicExtendedLength.HEADER_SIZE, 2, 2); - } -} +/** Parser state alias for backward compatibility */ +const BasicExtendedLengthParserState = GenericParserState; module.exports = { BasicExtendedLength, + BasicExtendedLengthConfig, BasicExtendedLengthParserState, }; diff --git a/src/struct_frame/boilerplate/js/BasicExtendedMsgIds.js b/src/struct_frame/boilerplate/js/BasicExtendedMsgIds.js index 4033a972..a390d7b6 100644 --- a/src/struct_frame/boilerplate/js/BasicExtendedMsgIds.js +++ b/src/struct_frame/boilerplate/js/BasicExtendedMsgIds.js @@ -1,135 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// BasicExtendedMsgIds Frame Format +// BasicExtendedMsgIds Frame Format Configuration // ============================================================================= -const BasicExtendedMsgIdsParserState = { - LOOKING_FOR_START1: 0, - LOOKING_FOR_START2: 1, - GETTING_MSG_ID: 2, - GETTING_LENGTH: 3, - GETTING_PAYLOAD: 4 +/** Configuration for BasicExtendedMsgIds frame format */ +const BasicExtendedMsgIdsConfig = { + name: 'BasicExtendedMsgIds', + startBytes: [0x90, 0x72], + headerSize: 5, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, }; /** * BasicExtendedMsgIds - Frame format parser and encoder + * + * Format: [START_BYTE1=0x90] [START_BYTE2=0x72] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class BasicExtendedMsgIds { - static START_BYTE1 = 0x90; - static START_BYTE2 = 0x72; - static HEADER_SIZE = 5; - static FOOTER_SIZE = 2; - static OVERHEAD = 7; - static LENGTH_BYTES = 1; +const BasicExtendedMsgIds = createFrameParserClass(BasicExtendedMsgIdsConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - reset() { - this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case BasicExtendedMsgIdsParserState.LOOKING_FOR_START1: - if (byte === BasicExtendedMsgIds.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START2; - } - break; - - case BasicExtendedMsgIdsParserState.LOOKING_FOR_START2: - if (byte === BasicExtendedMsgIds.START_BYTE2) { - this.buffer.push(byte); - this.state = BasicExtendedMsgIdsParserState.GETTING_MSG_ID; - } else if (byte === BasicExtendedMsgIds.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START2; - } else { - this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1; - } - break; - - case BasicExtendedMsgIdsParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = BasicExtendedMsgIdsParserState.GETTING_LENGTH; - break; - - case BasicExtendedMsgIdsParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = BasicExtendedMsgIds.OVERHEAD + this.msg_length; - this.state = BasicExtendedMsgIdsParserState.GETTING_PAYLOAD; - break; - - case BasicExtendedMsgIdsParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, BasicExtendedMsgIds.HEADER_SIZE, 1, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(BasicExtendedMsgIds.START_BYTE1); - output.push(BasicExtendedMsgIds.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 2); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < BasicExtendedMsgIds.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== BasicExtendedMsgIds.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== BasicExtendedMsgIds.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicExtendedMsgIds.HEADER_SIZE, 1, 2); - } -} +/** Parser state alias for backward compatibility */ +const BasicExtendedMsgIdsParserState = GenericParserState; module.exports = { BasicExtendedMsgIds, + BasicExtendedMsgIdsConfig, BasicExtendedMsgIdsParserState, }; diff --git a/src/struct_frame/boilerplate/js/BasicExtendedMultiSystemStream.js b/src/struct_frame/boilerplate/js/BasicExtendedMultiSystemStream.js index 6091a0e6..5a7d88b6 100644 --- a/src/struct_frame/boilerplate/js/BasicExtendedMultiSystemStream.js +++ b/src/struct_frame/boilerplate/js/BasicExtendedMultiSystemStream.js @@ -1,140 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// BasicExtendedMultiSystemStream Frame Format +// BasicExtendedMultiSystemStream Frame Format Configuration // ============================================================================= -const BasicExtendedMultiSystemStreamParserState = { - LOOKING_FOR_START1: 0, - LOOKING_FOR_START2: 1, - GETTING_MSG_ID: 2, - GETTING_LENGTH: 3, - GETTING_PAYLOAD: 4 +/** Configuration for BasicExtendedMultiSystemStream frame format */ +const BasicExtendedMultiSystemStreamConfig = { + name: 'BasicExtendedMultiSystemStream', + startBytes: [0x90, 0x78], + headerSize: 9, + footerSize: 2, + hasLength: true, + lengthBytes: 2, + hasCrc: true, }; /** * BasicExtendedMultiSystemStream - Frame format parser and encoder + * + * Format: [START_BYTE1=0x90] [START_BYTE2=0x78] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class BasicExtendedMultiSystemStream { - static START_BYTE1 = 0x90; - static START_BYTE2 = 0x78; - static HEADER_SIZE = 9; - static FOOTER_SIZE = 2; - static OVERHEAD = 11; - static LENGTH_BYTES = 2; +const BasicExtendedMultiSystemStream = createFrameParserClass(BasicExtendedMultiSystemStreamConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - this.length_lo = 0; - } - - reset() { - this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1: - if (byte === BasicExtendedMultiSystemStream.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START2; - } - break; - - case BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START2: - if (byte === BasicExtendedMultiSystemStream.START_BYTE2) { - this.buffer.push(byte); - this.state = BasicExtendedMultiSystemStreamParserState.GETTING_MSG_ID; - } else if (byte === BasicExtendedMultiSystemStream.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START2; - } else { - this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1; - } - break; - - case BasicExtendedMultiSystemStreamParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = BasicExtendedMultiSystemStreamParserState.GETTING_LENGTH; - break; - - case BasicExtendedMultiSystemStreamParserState.GETTING_LENGTH: - this.buffer.push(byte); - if (this.buffer.length === 4) { - this.length_lo = byte; - } else { - this.msg_length = this.length_lo | (byte << 8); - this.packet_size = BasicExtendedMultiSystemStream.OVERHEAD + this.msg_length; - this.state = BasicExtendedMultiSystemStreamParserState.GETTING_PAYLOAD; - } - break; - - case BasicExtendedMultiSystemStreamParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, BasicExtendedMultiSystemStream.HEADER_SIZE, 2, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(BasicExtendedMultiSystemStream.START_BYTE1); - output.push(BasicExtendedMultiSystemStream.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 2, 2); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < BasicExtendedMultiSystemStream.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== BasicExtendedMultiSystemStream.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== BasicExtendedMultiSystemStream.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicExtendedMultiSystemStream.HEADER_SIZE, 2, 2); - } -} +/** Parser state alias for backward compatibility */ +const BasicExtendedMultiSystemStreamParserState = GenericParserState; module.exports = { BasicExtendedMultiSystemStream, + BasicExtendedMultiSystemStreamConfig, BasicExtendedMultiSystemStreamParserState, }; diff --git a/src/struct_frame/boilerplate/js/BasicMinimal.js b/src/struct_frame/boilerplate/js/BasicMinimal.js index dddfd621..de7765aa 100644 --- a/src/struct_frame/boilerplate/js/BasicMinimal.js +++ b/src/struct_frame/boilerplate/js/BasicMinimal.js @@ -1,132 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// BasicMinimal Frame Format +// BasicMinimal Frame Format Configuration // ============================================================================= -const BasicMinimalParserState = { - LOOKING_FOR_START1: 0, - LOOKING_FOR_START2: 1, - GETTING_MSG_ID: 2, - GETTING_PAYLOAD: 3 +/** Configuration for BasicMinimal frame format */ +const BasicMinimalConfig = { + name: 'BasicMinimal', + startBytes: [0x90, 0x70], + headerSize: 3, + footerSize: 0, + hasLength: false, + lengthBytes: 0, + hasCrc: false, }; /** * BasicMinimal - Frame format parser and encoder + * + * Format: [START_BYTE1=0x90] [START_BYTE2=0x70] [MSG_ID] [MSG...] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class BasicMinimal { - static START_BYTE1 = 0x90; - static START_BYTE2 = 0x70; - static HEADER_SIZE = 3; - static FOOTER_SIZE = 0; - static OVERHEAD = 3; +const BasicMinimal = createFrameParserClass(BasicMinimalConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = BasicMinimalParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - } - - reset() { - this.state = BasicMinimalParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case BasicMinimalParserState.LOOKING_FOR_START1: - if (byte === BasicMinimal.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicMinimalParserState.LOOKING_FOR_START2; - } - break; - - case BasicMinimalParserState.LOOKING_FOR_START2: - if (byte === BasicMinimal.START_BYTE2) { - this.buffer.push(byte); - this.state = BasicMinimalParserState.GETTING_MSG_ID; - } else if (byte === BasicMinimal.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicMinimalParserState.LOOKING_FOR_START2; - } else { - this.state = BasicMinimalParserState.LOOKING_FOR_START1; - } - break; - - case BasicMinimalParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - if (this.get_msg_length) { - const msg_length = this.get_msg_length(byte); - if (msg_length !== undefined) { - this.packet_size = BasicMinimal.OVERHEAD + msg_length; - this.state = BasicMinimalParserState.GETTING_PAYLOAD; - } else { - this.state = BasicMinimalParserState.LOOKING_FOR_START1; - } - } else { - this.state = BasicMinimalParserState.LOOKING_FOR_START1; - } - break; - - case BasicMinimalParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared minimal payload validation - const validationResult = validate_payload_minimal(this.buffer, BasicMinimal.HEADER_SIZE); - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - this.state = BasicMinimalParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(BasicMinimal.START_BYTE1); - output.push(BasicMinimal.START_BYTE2); - // Use shared minimal payload encoding - encode_payload_minimal(output, msg_id, msg); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < BasicMinimal.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== BasicMinimal.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== BasicMinimal.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared minimal payload validation - return validate_payload_minimal(buffer, BasicMinimal.HEADER_SIZE); - } -} +/** Parser state alias for backward compatibility */ +const BasicMinimalParserState = GenericParserState; module.exports = { BasicMinimal, + BasicMinimalConfig, BasicMinimalParserState, }; diff --git a/src/struct_frame/boilerplate/js/BasicMultiSystemStream.js b/src/struct_frame/boilerplate/js/BasicMultiSystemStream.js index 0f8f464f..f4709a42 100644 --- a/src/struct_frame/boilerplate/js/BasicMultiSystemStream.js +++ b/src/struct_frame/boilerplate/js/BasicMultiSystemStream.js @@ -1,135 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// BasicMultiSystemStream Frame Format +// BasicMultiSystemStream Frame Format Configuration // ============================================================================= -const BasicMultiSystemStreamParserState = { - LOOKING_FOR_START1: 0, - LOOKING_FOR_START2: 1, - GETTING_MSG_ID: 2, - GETTING_LENGTH: 3, - GETTING_PAYLOAD: 4 +/** Configuration for BasicMultiSystemStream frame format */ +const BasicMultiSystemStreamConfig = { + name: 'BasicMultiSystemStream', + startBytes: [0x90, 0x77], + headerSize: 7, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, }; /** * BasicMultiSystemStream - Frame format parser and encoder + * + * Format: [START_BYTE1=0x90] [START_BYTE2=0x77] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class BasicMultiSystemStream { - static START_BYTE1 = 0x90; - static START_BYTE2 = 0x77; - static HEADER_SIZE = 7; - static FOOTER_SIZE = 2; - static OVERHEAD = 9; - static LENGTH_BYTES = 1; +const BasicMultiSystemStream = createFrameParserClass(BasicMultiSystemStreamConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - reset() { - this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case BasicMultiSystemStreamParserState.LOOKING_FOR_START1: - if (byte === BasicMultiSystemStream.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START2; - } - break; - - case BasicMultiSystemStreamParserState.LOOKING_FOR_START2: - if (byte === BasicMultiSystemStream.START_BYTE2) { - this.buffer.push(byte); - this.state = BasicMultiSystemStreamParserState.GETTING_MSG_ID; - } else if (byte === BasicMultiSystemStream.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START2; - } else { - this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1; - } - break; - - case BasicMultiSystemStreamParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = BasicMultiSystemStreamParserState.GETTING_LENGTH; - break; - - case BasicMultiSystemStreamParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = BasicMultiSystemStream.OVERHEAD + this.msg_length; - this.state = BasicMultiSystemStreamParserState.GETTING_PAYLOAD; - break; - - case BasicMultiSystemStreamParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, BasicMultiSystemStream.HEADER_SIZE, 1, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(BasicMultiSystemStream.START_BYTE1); - output.push(BasicMultiSystemStream.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 2); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < BasicMultiSystemStream.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== BasicMultiSystemStream.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== BasicMultiSystemStream.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicMultiSystemStream.HEADER_SIZE, 1, 2); - } -} +/** Parser state alias for backward compatibility */ +const BasicMultiSystemStreamParserState = GenericParserState; module.exports = { BasicMultiSystemStream, + BasicMultiSystemStreamConfig, BasicMultiSystemStreamParserState, }; diff --git a/src/struct_frame/boilerplate/js/BasicSeq.js b/src/struct_frame/boilerplate/js/BasicSeq.js index d97e9244..e7981273 100644 --- a/src/struct_frame/boilerplate/js/BasicSeq.js +++ b/src/struct_frame/boilerplate/js/BasicSeq.js @@ -1,135 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// BasicSeq Frame Format +// BasicSeq Frame Format Configuration // ============================================================================= -const BasicSeqParserState = { - LOOKING_FOR_START1: 0, - LOOKING_FOR_START2: 1, - GETTING_MSG_ID: 2, - GETTING_LENGTH: 3, - GETTING_PAYLOAD: 4 +/** Configuration for BasicSeq frame format */ +const BasicSeqConfig = { + name: 'BasicSeq', + startBytes: [0x90, 0x76], + headerSize: 5, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, }; /** * BasicSeq - Frame format parser and encoder + * + * Format: [START_BYTE1=0x90] [START_BYTE2=0x76] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class BasicSeq { - static START_BYTE1 = 0x90; - static START_BYTE2 = 0x76; - static HEADER_SIZE = 5; - static FOOTER_SIZE = 2; - static OVERHEAD = 7; - static LENGTH_BYTES = 1; +const BasicSeq = createFrameParserClass(BasicSeqConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = BasicSeqParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - reset() { - this.state = BasicSeqParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case BasicSeqParserState.LOOKING_FOR_START1: - if (byte === BasicSeq.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicSeqParserState.LOOKING_FOR_START2; - } - break; - - case BasicSeqParserState.LOOKING_FOR_START2: - if (byte === BasicSeq.START_BYTE2) { - this.buffer.push(byte); - this.state = BasicSeqParserState.GETTING_MSG_ID; - } else if (byte === BasicSeq.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicSeqParserState.LOOKING_FOR_START2; - } else { - this.state = BasicSeqParserState.LOOKING_FOR_START1; - } - break; - - case BasicSeqParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = BasicSeqParserState.GETTING_LENGTH; - break; - - case BasicSeqParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = BasicSeq.OVERHEAD + this.msg_length; - this.state = BasicSeqParserState.GETTING_PAYLOAD; - break; - - case BasicSeqParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, BasicSeq.HEADER_SIZE, 1, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = BasicSeqParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(BasicSeq.START_BYTE1); - output.push(BasicSeq.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 2); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < BasicSeq.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== BasicSeq.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== BasicSeq.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicSeq.HEADER_SIZE, 1, 2); - } -} +/** Parser state alias for backward compatibility */ +const BasicSeqParserState = GenericParserState; module.exports = { BasicSeq, + BasicSeqConfig, BasicSeqParserState, }; diff --git a/src/struct_frame/boilerplate/js/BasicSysComp.js b/src/struct_frame/boilerplate/js/BasicSysComp.js index 541e352c..d5239a4d 100644 --- a/src/struct_frame/boilerplate/js/BasicSysComp.js +++ b/src/struct_frame/boilerplate/js/BasicSysComp.js @@ -1,135 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// BasicSysComp Frame Format +// BasicSysComp Frame Format Configuration // ============================================================================= -const BasicSysCompParserState = { - LOOKING_FOR_START1: 0, - LOOKING_FOR_START2: 1, - GETTING_MSG_ID: 2, - GETTING_LENGTH: 3, - GETTING_PAYLOAD: 4 +/** Configuration for BasicSysComp frame format */ +const BasicSysCompConfig = { + name: 'BasicSysComp', + startBytes: [0x90, 0x75], + headerSize: 6, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, }; /** * BasicSysComp - Frame format parser and encoder + * + * Format: [START_BYTE1=0x90] [START_BYTE2=0x75] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class BasicSysComp { - static START_BYTE1 = 0x90; - static START_BYTE2 = 0x75; - static HEADER_SIZE = 6; - static FOOTER_SIZE = 2; - static OVERHEAD = 8; - static LENGTH_BYTES = 1; +const BasicSysComp = createFrameParserClass(BasicSysCompConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = BasicSysCompParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - reset() { - this.state = BasicSysCompParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case BasicSysCompParserState.LOOKING_FOR_START1: - if (byte === BasicSysComp.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicSysCompParserState.LOOKING_FOR_START2; - } - break; - - case BasicSysCompParserState.LOOKING_FOR_START2: - if (byte === BasicSysComp.START_BYTE2) { - this.buffer.push(byte); - this.state = BasicSysCompParserState.GETTING_MSG_ID; - } else if (byte === BasicSysComp.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicSysCompParserState.LOOKING_FOR_START2; - } else { - this.state = BasicSysCompParserState.LOOKING_FOR_START1; - } - break; - - case BasicSysCompParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = BasicSysCompParserState.GETTING_LENGTH; - break; - - case BasicSysCompParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = BasicSysComp.OVERHEAD + this.msg_length; - this.state = BasicSysCompParserState.GETTING_PAYLOAD; - break; - - case BasicSysCompParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, BasicSysComp.HEADER_SIZE, 1, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = BasicSysCompParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(BasicSysComp.START_BYTE1); - output.push(BasicSysComp.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 2); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < BasicSysComp.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== BasicSysComp.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== BasicSysComp.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicSysComp.HEADER_SIZE, 1, 2); - } -} +/** Parser state alias for backward compatibility */ +const BasicSysCompParserState = GenericParserState; module.exports = { BasicSysComp, + BasicSysCompConfig, BasicSysCompParserState, }; diff --git a/src/struct_frame/boilerplate/js/FrameFormatConfig.js b/src/struct_frame/boilerplate/js/FrameFormatConfig.js index b301bc79..a327cfe4 100644 --- a/src/struct_frame/boilerplate/js/FrameFormatConfig.js +++ b/src/struct_frame/boilerplate/js/FrameFormatConfig.js @@ -1,134 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// FrameFormatConfig Frame Format +// FrameFormatConfig Frame Format Configuration // ============================================================================= -const FrameFormatConfigParserState = { - LOOKING_FOR_START1: 0, - LOOKING_FOR_START2: 1, - GETTING_MSG_ID: 2, - GETTING_PAYLOAD: 3 +/** Configuration for FrameFormatConfig frame format */ +const FrameFormatConfigConfig = { + name: 'FrameFormatConfig', + startBytes: [0x90, 0x71], + headerSize: 2, + footerSize: 1, + hasLength: false, + lengthBytes: 0, + hasCrc: true, }; /** * FrameFormatConfig - Frame format parser and encoder + * + * Format: [START_BYTE1=0x90] [START_BYTE2=0x71] [MSG_ID] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class FrameFormatConfig { - static START_BYTE1 = 0x90; - static START_BYTE2 = 0x71; - static HEADER_SIZE = 2; - static FOOTER_SIZE = 1; - static OVERHEAD = 3; +const FrameFormatConfig = createFrameParserClass(FrameFormatConfigConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = FrameFormatConfigParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - } - - reset() { - this.state = FrameFormatConfigParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case FrameFormatConfigParserState.LOOKING_FOR_START1: - if (byte === FrameFormatConfig.START_BYTE1) { - this.buffer = [byte]; - this.state = FrameFormatConfigParserState.LOOKING_FOR_START2; - } - break; - - case FrameFormatConfigParserState.LOOKING_FOR_START2: - if (byte === FrameFormatConfig.START_BYTE2) { - this.buffer.push(byte); - this.state = FrameFormatConfigParserState.GETTING_MSG_ID; - } else if (byte === FrameFormatConfig.START_BYTE1) { - this.buffer = [byte]; - this.state = FrameFormatConfigParserState.LOOKING_FOR_START2; - } else { - this.state = FrameFormatConfigParserState.LOOKING_FOR_START1; - } - break; - - case FrameFormatConfigParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - if (this.get_msg_length) { - const msg_length = this.get_msg_length(byte); - if (msg_length !== undefined) { - this.packet_size = FrameFormatConfig.OVERHEAD + msg_length; - this.state = FrameFormatConfigParserState.GETTING_PAYLOAD; - } else { - this.state = FrameFormatConfigParserState.LOOKING_FOR_START1; - } - } else { - this.state = FrameFormatConfigParserState.LOOKING_FOR_START1; - } - break; - - case FrameFormatConfigParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, FrameFormatConfig.HEADER_SIZE, 0, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = FrameFormatConfigParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(FrameFormatConfig.START_BYTE1); - output.push(FrameFormatConfig.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 0, 2); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < FrameFormatConfig.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== FrameFormatConfig.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== FrameFormatConfig.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, FrameFormatConfig.HEADER_SIZE, 0, 2); - } -} +/** Parser state alias for backward compatibility */ +const FrameFormatConfigParserState = GenericParserState; module.exports = { FrameFormatConfig, + FrameFormatConfigConfig, FrameFormatConfigParserState, }; diff --git a/src/struct_frame/boilerplate/js/MavlinkV1Frame.js b/src/struct_frame/boilerplate/js/MavlinkV1Frame.js index 64220368..5db888ea 100644 --- a/src/struct_frame/boilerplate/js/MavlinkV1Frame.js +++ b/src/struct_frame/boilerplate/js/MavlinkV1Frame.js @@ -1,117 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// MavlinkV1Frame Frame Format +// MavlinkV1Frame Frame Format Configuration // ============================================================================= -const MavlinkV1FrameParserState = { - LOOKING_FOR_START: 0, - GETTING_MSG_ID: 1, - GETTING_LENGTH: 2, - GETTING_PAYLOAD: 3 +/** Configuration for MavlinkV1Frame frame format */ +const MavlinkV1FrameConfig = { + name: 'MavlinkV1Frame', + startBytes: [0xFE], + headerSize: 6, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, }; /** * MavlinkV1Frame - Frame format parser and encoder + * + * Format: [STX=0xFE] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class MavlinkV1Frame { - static START_BYTE = 0xFE; - static HEADER_SIZE = 6; - static FOOTER_SIZE = 2; - static OVERHEAD = 8; - static LENGTH_BYTES = 1; +const MavlinkV1Frame = createFrameParserClass(MavlinkV1FrameConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = MavlinkV1FrameParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - reset() { - this.state = MavlinkV1FrameParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case MavlinkV1FrameParserState.LOOKING_FOR_START: - if (byte === MavlinkV1Frame.START_BYTE) { - this.buffer = [byte]; - this.state = MavlinkV1FrameParserState.GETTING_MSG_ID; - } - break; - - case MavlinkV1FrameParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = MavlinkV1FrameParserState.GETTING_LENGTH; - break; - - case MavlinkV1FrameParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = MavlinkV1Frame.OVERHEAD + this.msg_length; - this.state = MavlinkV1FrameParserState.GETTING_PAYLOAD; - break; - - case MavlinkV1FrameParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, MavlinkV1Frame.HEADER_SIZE, 1, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = MavlinkV1FrameParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(MavlinkV1Frame.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < MavlinkV1Frame.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== MavlinkV1Frame.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, MavlinkV1Frame.HEADER_SIZE, 1, 1); - } -} +/** Parser state alias for backward compatibility */ +const MavlinkV1FrameParserState = GenericParserState; module.exports = { MavlinkV1Frame, + MavlinkV1FrameConfig, MavlinkV1FrameParserState, }; diff --git a/src/struct_frame/boilerplate/js/MavlinkV2Frame.js b/src/struct_frame/boilerplate/js/MavlinkV2Frame.js index be06bbba..c76d73c1 100644 --- a/src/struct_frame/boilerplate/js/MavlinkV2Frame.js +++ b/src/struct_frame/boilerplate/js/MavlinkV2Frame.js @@ -1,117 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// MavlinkV2Frame Frame Format +// MavlinkV2Frame Frame Format Configuration // ============================================================================= -const MavlinkV2FrameParserState = { - LOOKING_FOR_START: 0, - GETTING_MSG_ID: 1, - GETTING_LENGTH: 2, - GETTING_PAYLOAD: 3 +/** Configuration for MavlinkV2Frame frame format */ +const MavlinkV2FrameConfig = { + name: 'MavlinkV2Frame', + startBytes: [0xFD], + headerSize: 8, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, }; /** * MavlinkV2Frame - Frame format parser and encoder + * + * Format: [STX=0xFD] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class MavlinkV2Frame { - static START_BYTE = 0xFD; - static HEADER_SIZE = 8; - static FOOTER_SIZE = 2; - static OVERHEAD = 10; - static LENGTH_BYTES = 1; +const MavlinkV2Frame = createFrameParserClass(MavlinkV2FrameConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = MavlinkV2FrameParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - reset() { - this.state = MavlinkV2FrameParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case MavlinkV2FrameParserState.LOOKING_FOR_START: - if (byte === MavlinkV2Frame.START_BYTE) { - this.buffer = [byte]; - this.state = MavlinkV2FrameParserState.GETTING_MSG_ID; - } - break; - - case MavlinkV2FrameParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = MavlinkV2FrameParserState.GETTING_LENGTH; - break; - - case MavlinkV2FrameParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = MavlinkV2Frame.OVERHEAD + this.msg_length; - this.state = MavlinkV2FrameParserState.GETTING_PAYLOAD; - break; - - case MavlinkV2FrameParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, MavlinkV2Frame.HEADER_SIZE, 1, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = MavlinkV2FrameParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(MavlinkV2Frame.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < MavlinkV2Frame.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== MavlinkV2Frame.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, MavlinkV2Frame.HEADER_SIZE, 1, 1); - } -} +/** Parser state alias for backward compatibility */ +const MavlinkV2FrameParserState = GenericParserState; module.exports = { MavlinkV2Frame, + MavlinkV2FrameConfig, MavlinkV2FrameParserState, }; diff --git a/src/struct_frame/boilerplate/js/TinyDefault.js b/src/struct_frame/boilerplate/js/TinyDefault.js index 8c461a57..0e89ac08 100644 --- a/src/struct_frame/boilerplate/js/TinyDefault.js +++ b/src/struct_frame/boilerplate/js/TinyDefault.js @@ -1,117 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// TinyDefault Frame Format +// TinyDefault Frame Format Configuration // ============================================================================= -const TinyDefaultParserState = { - LOOKING_FOR_START: 0, - GETTING_MSG_ID: 1, - GETTING_LENGTH: 2, - GETTING_PAYLOAD: 3 +/** Configuration for TinyDefault frame format */ +const TinyDefaultConfig = { + name: 'TinyDefault', + startBytes: [0x71], + headerSize: 3, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, }; /** * TinyDefault - Frame format parser and encoder + * + * Format: [START_BYTE=0x71] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class TinyDefault { - static START_BYTE = 0x71; - static HEADER_SIZE = 3; - static FOOTER_SIZE = 2; - static OVERHEAD = 5; - static LENGTH_BYTES = 1; +const TinyDefault = createFrameParserClass(TinyDefaultConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = TinyDefaultParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - reset() { - this.state = TinyDefaultParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case TinyDefaultParserState.LOOKING_FOR_START: - if (byte === TinyDefault.START_BYTE) { - this.buffer = [byte]; - this.state = TinyDefaultParserState.GETTING_MSG_ID; - } - break; - - case TinyDefaultParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = TinyDefaultParserState.GETTING_LENGTH; - break; - - case TinyDefaultParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = TinyDefault.OVERHEAD + this.msg_length; - this.state = TinyDefaultParserState.GETTING_PAYLOAD; - break; - - case TinyDefaultParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, TinyDefault.HEADER_SIZE, 1, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = TinyDefaultParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(TinyDefault.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < TinyDefault.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== TinyDefault.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinyDefault.HEADER_SIZE, 1, 1); - } -} +/** Parser state alias for backward compatibility */ +const TinyDefaultParserState = GenericParserState; module.exports = { TinyDefault, + TinyDefaultConfig, TinyDefaultParserState, }; diff --git a/src/struct_frame/boilerplate/js/TinyExtended.js b/src/struct_frame/boilerplate/js/TinyExtended.js index 396b6048..04209afb 100644 --- a/src/struct_frame/boilerplate/js/TinyExtended.js +++ b/src/struct_frame/boilerplate/js/TinyExtended.js @@ -1,122 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// TinyExtended Frame Format +// TinyExtended Frame Format Configuration // ============================================================================= -const TinyExtendedParserState = { - LOOKING_FOR_START: 0, - GETTING_MSG_ID: 1, - GETTING_LENGTH: 2, - GETTING_PAYLOAD: 3 +/** Configuration for TinyExtended frame format */ +const TinyExtendedConfig = { + name: 'TinyExtended', + startBytes: [0x74], + headerSize: 5, + footerSize: 2, + hasLength: true, + lengthBytes: 2, + hasCrc: true, }; /** * TinyExtended - Frame format parser and encoder + * + * Format: [START_BYTE=0x74] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class TinyExtended { - static START_BYTE = 0x74; - static HEADER_SIZE = 5; - static FOOTER_SIZE = 2; - static OVERHEAD = 7; - static LENGTH_BYTES = 2; +const TinyExtended = createFrameParserClass(TinyExtendedConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = TinyExtendedParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - this.length_lo = 0; - } - - reset() { - this.state = TinyExtendedParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case TinyExtendedParserState.LOOKING_FOR_START: - if (byte === TinyExtended.START_BYTE) { - this.buffer = [byte]; - this.state = TinyExtendedParserState.GETTING_MSG_ID; - } - break; - - case TinyExtendedParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = TinyExtendedParserState.GETTING_LENGTH; - break; - - case TinyExtendedParserState.GETTING_LENGTH: - this.buffer.push(byte); - if (this.buffer.length === 3) { - this.length_lo = byte; - } else { - this.msg_length = this.length_lo | (byte << 8); - this.packet_size = TinyExtended.OVERHEAD + this.msg_length; - this.state = TinyExtendedParserState.GETTING_PAYLOAD; - } - break; - - case TinyExtendedParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, TinyExtended.HEADER_SIZE, 2, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = TinyExtendedParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(TinyExtended.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 2, 1); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < TinyExtended.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== TinyExtended.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinyExtended.HEADER_SIZE, 2, 1); - } -} +/** Parser state alias for backward compatibility */ +const TinyExtendedParserState = GenericParserState; module.exports = { TinyExtended, + TinyExtendedConfig, TinyExtendedParserState, }; diff --git a/src/struct_frame/boilerplate/js/TinyExtendedLength.js b/src/struct_frame/boilerplate/js/TinyExtendedLength.js index 1020dd17..f62bac8d 100644 --- a/src/struct_frame/boilerplate/js/TinyExtendedLength.js +++ b/src/struct_frame/boilerplate/js/TinyExtendedLength.js @@ -1,122 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// TinyExtendedLength Frame Format +// TinyExtendedLength Frame Format Configuration // ============================================================================= -const TinyExtendedLengthParserState = { - LOOKING_FOR_START: 0, - GETTING_MSG_ID: 1, - GETTING_LENGTH: 2, - GETTING_PAYLOAD: 3 +/** Configuration for TinyExtendedLength frame format */ +const TinyExtendedLengthConfig = { + name: 'TinyExtendedLength', + startBytes: [0x73], + headerSize: 4, + footerSize: 2, + hasLength: true, + lengthBytes: 2, + hasCrc: true, }; /** * TinyExtendedLength - Frame format parser and encoder + * + * Format: [START_BYTE=0x73] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class TinyExtendedLength { - static START_BYTE = 0x73; - static HEADER_SIZE = 4; - static FOOTER_SIZE = 2; - static OVERHEAD = 6; - static LENGTH_BYTES = 2; +const TinyExtendedLength = createFrameParserClass(TinyExtendedLengthConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = TinyExtendedLengthParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - this.length_lo = 0; - } - - reset() { - this.state = TinyExtendedLengthParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case TinyExtendedLengthParserState.LOOKING_FOR_START: - if (byte === TinyExtendedLength.START_BYTE) { - this.buffer = [byte]; - this.state = TinyExtendedLengthParserState.GETTING_MSG_ID; - } - break; - - case TinyExtendedLengthParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = TinyExtendedLengthParserState.GETTING_LENGTH; - break; - - case TinyExtendedLengthParserState.GETTING_LENGTH: - this.buffer.push(byte); - if (this.buffer.length === 3) { - this.length_lo = byte; - } else { - this.msg_length = this.length_lo | (byte << 8); - this.packet_size = TinyExtendedLength.OVERHEAD + this.msg_length; - this.state = TinyExtendedLengthParserState.GETTING_PAYLOAD; - } - break; - - case TinyExtendedLengthParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, TinyExtendedLength.HEADER_SIZE, 2, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = TinyExtendedLengthParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(TinyExtendedLength.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 2, 1); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < TinyExtendedLength.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== TinyExtendedLength.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinyExtendedLength.HEADER_SIZE, 2, 1); - } -} +/** Parser state alias for backward compatibility */ +const TinyExtendedLengthParserState = GenericParserState; module.exports = { TinyExtendedLength, + TinyExtendedLengthConfig, TinyExtendedLengthParserState, }; diff --git a/src/struct_frame/boilerplate/js/TinyExtendedMsgIds.js b/src/struct_frame/boilerplate/js/TinyExtendedMsgIds.js index cbad6208..d9b3820d 100644 --- a/src/struct_frame/boilerplate/js/TinyExtendedMsgIds.js +++ b/src/struct_frame/boilerplate/js/TinyExtendedMsgIds.js @@ -1,117 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// TinyExtendedMsgIds Frame Format +// TinyExtendedMsgIds Frame Format Configuration // ============================================================================= -const TinyExtendedMsgIdsParserState = { - LOOKING_FOR_START: 0, - GETTING_MSG_ID: 1, - GETTING_LENGTH: 2, - GETTING_PAYLOAD: 3 +/** Configuration for TinyExtendedMsgIds frame format */ +const TinyExtendedMsgIdsConfig = { + name: 'TinyExtendedMsgIds', + startBytes: [0x72], + headerSize: 4, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, }; /** * TinyExtendedMsgIds - Frame format parser and encoder + * + * Format: [START_BYTE=0x72] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class TinyExtendedMsgIds { - static START_BYTE = 0x72; - static HEADER_SIZE = 4; - static FOOTER_SIZE = 2; - static OVERHEAD = 6; - static LENGTH_BYTES = 1; +const TinyExtendedMsgIds = createFrameParserClass(TinyExtendedMsgIdsConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = TinyExtendedMsgIdsParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - reset() { - this.state = TinyExtendedMsgIdsParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case TinyExtendedMsgIdsParserState.LOOKING_FOR_START: - if (byte === TinyExtendedMsgIds.START_BYTE) { - this.buffer = [byte]; - this.state = TinyExtendedMsgIdsParserState.GETTING_MSG_ID; - } - break; - - case TinyExtendedMsgIdsParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = TinyExtendedMsgIdsParserState.GETTING_LENGTH; - break; - - case TinyExtendedMsgIdsParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = TinyExtendedMsgIds.OVERHEAD + this.msg_length; - this.state = TinyExtendedMsgIdsParserState.GETTING_PAYLOAD; - break; - - case TinyExtendedMsgIdsParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, TinyExtendedMsgIds.HEADER_SIZE, 1, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = TinyExtendedMsgIdsParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(TinyExtendedMsgIds.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < TinyExtendedMsgIds.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== TinyExtendedMsgIds.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinyExtendedMsgIds.HEADER_SIZE, 1, 1); - } -} +/** Parser state alias for backward compatibility */ +const TinyExtendedMsgIdsParserState = GenericParserState; module.exports = { TinyExtendedMsgIds, + TinyExtendedMsgIdsConfig, TinyExtendedMsgIdsParserState, }; diff --git a/src/struct_frame/boilerplate/js/TinyExtendedMultiSystemStream.js b/src/struct_frame/boilerplate/js/TinyExtendedMultiSystemStream.js index c108a4f8..0400df4b 100644 --- a/src/struct_frame/boilerplate/js/TinyExtendedMultiSystemStream.js +++ b/src/struct_frame/boilerplate/js/TinyExtendedMultiSystemStream.js @@ -1,122 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// TinyExtendedMultiSystemStream Frame Format +// TinyExtendedMultiSystemStream Frame Format Configuration // ============================================================================= -const TinyExtendedMultiSystemStreamParserState = { - LOOKING_FOR_START: 0, - GETTING_MSG_ID: 1, - GETTING_LENGTH: 2, - GETTING_PAYLOAD: 3 +/** Configuration for TinyExtendedMultiSystemStream frame format */ +const TinyExtendedMultiSystemStreamConfig = { + name: 'TinyExtendedMultiSystemStream', + startBytes: [0x78], + headerSize: 8, + footerSize: 2, + hasLength: true, + lengthBytes: 2, + hasCrc: true, }; /** * TinyExtendedMultiSystemStream - Frame format parser and encoder + * + * Format: [START_BYTE=0x78] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class TinyExtendedMultiSystemStream { - static START_BYTE = 0x78; - static HEADER_SIZE = 8; - static FOOTER_SIZE = 2; - static OVERHEAD = 10; - static LENGTH_BYTES = 2; +const TinyExtendedMultiSystemStream = createFrameParserClass(TinyExtendedMultiSystemStreamConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - this.length_lo = 0; - } - - reset() { - this.state = TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START: - if (byte === TinyExtendedMultiSystemStream.START_BYTE) { - this.buffer = [byte]; - this.state = TinyExtendedMultiSystemStreamParserState.GETTING_MSG_ID; - } - break; - - case TinyExtendedMultiSystemStreamParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = TinyExtendedMultiSystemStreamParserState.GETTING_LENGTH; - break; - - case TinyExtendedMultiSystemStreamParserState.GETTING_LENGTH: - this.buffer.push(byte); - if (this.buffer.length === 3) { - this.length_lo = byte; - } else { - this.msg_length = this.length_lo | (byte << 8); - this.packet_size = TinyExtendedMultiSystemStream.OVERHEAD + this.msg_length; - this.state = TinyExtendedMultiSystemStreamParserState.GETTING_PAYLOAD; - } - break; - - case TinyExtendedMultiSystemStreamParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, TinyExtendedMultiSystemStream.HEADER_SIZE, 2, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(TinyExtendedMultiSystemStream.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 2, 1); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < TinyExtendedMultiSystemStream.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== TinyExtendedMultiSystemStream.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinyExtendedMultiSystemStream.HEADER_SIZE, 2, 1); - } -} +/** Parser state alias for backward compatibility */ +const TinyExtendedMultiSystemStreamParserState = GenericParserState; module.exports = { TinyExtendedMultiSystemStream, + TinyExtendedMultiSystemStreamConfig, TinyExtendedMultiSystemStreamParserState, }; diff --git a/src/struct_frame/boilerplate/js/TinyMinimal.js b/src/struct_frame/boilerplate/js/TinyMinimal.js index dc703ef0..b5b51f42 100644 --- a/src/struct_frame/boilerplate/js/TinyMinimal.js +++ b/src/struct_frame/boilerplate/js/TinyMinimal.js @@ -1,114 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// TinyMinimal Frame Format +// TinyMinimal Frame Format Configuration // ============================================================================= -const TinyMinimalParserState = { - LOOKING_FOR_START: 0, - GETTING_MSG_ID: 1, - GETTING_PAYLOAD: 2 +/** Configuration for TinyMinimal frame format */ +const TinyMinimalConfig = { + name: 'TinyMinimal', + startBytes: [0x70], + headerSize: 2, + footerSize: 0, + hasLength: false, + lengthBytes: 0, + hasCrc: false, }; /** * TinyMinimal - Frame format parser and encoder + * + * Format: [START_BYTE=0x70] [MSG_ID] [MSG...] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class TinyMinimal { - static START_BYTE = 0x70; - static HEADER_SIZE = 2; - static FOOTER_SIZE = 0; - static OVERHEAD = 2; +const TinyMinimal = createFrameParserClass(TinyMinimalConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = TinyMinimalParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - } - - reset() { - this.state = TinyMinimalParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case TinyMinimalParserState.LOOKING_FOR_START: - if (byte === TinyMinimal.START_BYTE) { - this.buffer = [byte]; - this.state = TinyMinimalParserState.GETTING_MSG_ID; - } - break; - - case TinyMinimalParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - if (this.get_msg_length) { - const msg_length = this.get_msg_length(byte); - if (msg_length !== undefined) { - this.packet_size = TinyMinimal.OVERHEAD + msg_length; - this.state = TinyMinimalParserState.GETTING_PAYLOAD; - } else { - this.state = TinyMinimalParserState.LOOKING_FOR_START; - } - } else { - this.state = TinyMinimalParserState.LOOKING_FOR_START; - } - break; - - case TinyMinimalParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared minimal payload validation - const validationResult = validate_payload_minimal(this.buffer, TinyMinimal.HEADER_SIZE); - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - this.state = TinyMinimalParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(TinyMinimal.START_BYTE); - // Use shared minimal payload encoding - encode_payload_minimal(output, msg_id, msg); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < TinyMinimal.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== TinyMinimal.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared minimal payload validation - return validate_payload_minimal(buffer, TinyMinimal.HEADER_SIZE); - } -} +/** Parser state alias for backward compatibility */ +const TinyMinimalParserState = GenericParserState; module.exports = { TinyMinimal, + TinyMinimalConfig, TinyMinimalParserState, }; diff --git a/src/struct_frame/boilerplate/js/TinyMultiSystemStream.js b/src/struct_frame/boilerplate/js/TinyMultiSystemStream.js index b8eb8cfe..045563c8 100644 --- a/src/struct_frame/boilerplate/js/TinyMultiSystemStream.js +++ b/src/struct_frame/boilerplate/js/TinyMultiSystemStream.js @@ -1,117 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// TinyMultiSystemStream Frame Format +// TinyMultiSystemStream Frame Format Configuration // ============================================================================= -const TinyMultiSystemStreamParserState = { - LOOKING_FOR_START: 0, - GETTING_MSG_ID: 1, - GETTING_LENGTH: 2, - GETTING_PAYLOAD: 3 +/** Configuration for TinyMultiSystemStream frame format */ +const TinyMultiSystemStreamConfig = { + name: 'TinyMultiSystemStream', + startBytes: [0x77], + headerSize: 6, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, }; /** * TinyMultiSystemStream - Frame format parser and encoder + * + * Format: [START_BYTE=0x77] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class TinyMultiSystemStream { - static START_BYTE = 0x77; - static HEADER_SIZE = 6; - static FOOTER_SIZE = 2; - static OVERHEAD = 8; - static LENGTH_BYTES = 1; +const TinyMultiSystemStream = createFrameParserClass(TinyMultiSystemStreamConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = TinyMultiSystemStreamParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - reset() { - this.state = TinyMultiSystemStreamParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case TinyMultiSystemStreamParserState.LOOKING_FOR_START: - if (byte === TinyMultiSystemStream.START_BYTE) { - this.buffer = [byte]; - this.state = TinyMultiSystemStreamParserState.GETTING_MSG_ID; - } - break; - - case TinyMultiSystemStreamParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = TinyMultiSystemStreamParserState.GETTING_LENGTH; - break; - - case TinyMultiSystemStreamParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = TinyMultiSystemStream.OVERHEAD + this.msg_length; - this.state = TinyMultiSystemStreamParserState.GETTING_PAYLOAD; - break; - - case TinyMultiSystemStreamParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, TinyMultiSystemStream.HEADER_SIZE, 1, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = TinyMultiSystemStreamParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(TinyMultiSystemStream.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < TinyMultiSystemStream.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== TinyMultiSystemStream.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinyMultiSystemStream.HEADER_SIZE, 1, 1); - } -} +/** Parser state alias for backward compatibility */ +const TinyMultiSystemStreamParserState = GenericParserState; module.exports = { TinyMultiSystemStream, + TinyMultiSystemStreamConfig, TinyMultiSystemStreamParserState, }; diff --git a/src/struct_frame/boilerplate/js/TinySeq.js b/src/struct_frame/boilerplate/js/TinySeq.js index 931624dc..b3cad8bc 100644 --- a/src/struct_frame/boilerplate/js/TinySeq.js +++ b/src/struct_frame/boilerplate/js/TinySeq.js @@ -1,117 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// TinySeq Frame Format +// TinySeq Frame Format Configuration // ============================================================================= -const TinySeqParserState = { - LOOKING_FOR_START: 0, - GETTING_MSG_ID: 1, - GETTING_LENGTH: 2, - GETTING_PAYLOAD: 3 +/** Configuration for TinySeq frame format */ +const TinySeqConfig = { + name: 'TinySeq', + startBytes: [0x76], + headerSize: 4, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, }; /** * TinySeq - Frame format parser and encoder + * + * Format: [START_BYTE=0x76] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class TinySeq { - static START_BYTE = 0x76; - static HEADER_SIZE = 4; - static FOOTER_SIZE = 2; - static OVERHEAD = 6; - static LENGTH_BYTES = 1; +const TinySeq = createFrameParserClass(TinySeqConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = TinySeqParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - reset() { - this.state = TinySeqParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case TinySeqParserState.LOOKING_FOR_START: - if (byte === TinySeq.START_BYTE) { - this.buffer = [byte]; - this.state = TinySeqParserState.GETTING_MSG_ID; - } - break; - - case TinySeqParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = TinySeqParserState.GETTING_LENGTH; - break; - - case TinySeqParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = TinySeq.OVERHEAD + this.msg_length; - this.state = TinySeqParserState.GETTING_PAYLOAD; - break; - - case TinySeqParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, TinySeq.HEADER_SIZE, 1, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = TinySeqParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(TinySeq.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < TinySeq.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== TinySeq.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinySeq.HEADER_SIZE, 1, 1); - } -} +/** Parser state alias for backward compatibility */ +const TinySeqParserState = GenericParserState; module.exports = { TinySeq, + TinySeqConfig, TinySeqParserState, }; diff --git a/src/struct_frame/boilerplate/js/TinySysComp.js b/src/struct_frame/boilerplate/js/TinySysComp.js index 17d05f9d..6cebbe1f 100644 --- a/src/struct_frame/boilerplate/js/TinySysComp.js +++ b/src/struct_frame/boilerplate/js/TinySysComp.js @@ -1,117 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// TinySysComp Frame Format +// TinySysComp Frame Format Configuration // ============================================================================= -const TinySysCompParserState = { - LOOKING_FOR_START: 0, - GETTING_MSG_ID: 1, - GETTING_LENGTH: 2, - GETTING_PAYLOAD: 3 +/** Configuration for TinySysComp frame format */ +const TinySysCompConfig = { + name: 'TinySysComp', + startBytes: [0x75], + headerSize: 5, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, }; /** * TinySysComp - Frame format parser and encoder + * + * Format: [START_BYTE=0x75] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class TinySysComp { - static START_BYTE = 0x75; - static HEADER_SIZE = 5; - static FOOTER_SIZE = 2; - static OVERHEAD = 7; - static LENGTH_BYTES = 1; +const TinySysComp = createFrameParserClass(TinySysCompConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = TinySysCompParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - reset() { - this.state = TinySysCompParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case TinySysCompParserState.LOOKING_FOR_START: - if (byte === TinySysComp.START_BYTE) { - this.buffer = [byte]; - this.state = TinySysCompParserState.GETTING_MSG_ID; - } - break; - - case TinySysCompParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = TinySysCompParserState.GETTING_LENGTH; - break; - - case TinySysCompParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = TinySysComp.OVERHEAD + this.msg_length; - this.state = TinySysCompParserState.GETTING_PAYLOAD; - break; - - case TinySysCompParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, TinySysComp.HEADER_SIZE, 1, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = TinySysCompParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(TinySysComp.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < TinySysComp.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== TinySysComp.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinySysComp.HEADER_SIZE, 1, 1); - } -} +/** Parser state alias for backward compatibility */ +const TinySysCompParserState = GenericParserState; module.exports = { TinySysComp, + TinySysCompConfig, TinySysCompParserState, }; diff --git a/src/struct_frame/boilerplate/js/UbxFrame.js b/src/struct_frame/boilerplate/js/UbxFrame.js index 4ef06951..cf67599f 100644 --- a/src/struct_frame/boilerplate/js/UbxFrame.js +++ b/src/struct_frame/boilerplate/js/UbxFrame.js @@ -1,135 +1,39 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. const { - createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + createFrameParserClass, GenericParserState, } = require('./frame_base'); // ============================================================================= -// UbxFrame Frame Format +// UbxFrame Frame Format Configuration // ============================================================================= -const UbxFrameParserState = { - LOOKING_FOR_START1: 0, - LOOKING_FOR_START2: 1, - GETTING_MSG_ID: 2, - GETTING_LENGTH: 3, - GETTING_PAYLOAD: 4 +/** Configuration for UbxFrame frame format */ +const UbxFrameConfig = { + name: 'UbxFrame', + startBytes: [0xB5, 0x62], + headerSize: 5, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, }; /** * UbxFrame - Frame format parser and encoder + * + * Format: [SYNC1=0xB5] [SYNC2=0x62] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -class UbxFrame { - static START_BYTE1 = 0xB5; - static START_BYTE2 = 0x62; - static HEADER_SIZE = 5; - static FOOTER_SIZE = 2; - static OVERHEAD = 7; - static LENGTH_BYTES = 1; +const UbxFrame = createFrameParserClass(UbxFrameConfig); - constructor(get_msg_length) { - this.get_msg_length = get_msg_length; - this.state = UbxFrameParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - reset() { - this.state = UbxFrameParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - parse_byte(byte) { - const result = createFrameMsgInfo(); - - switch (this.state) { - case UbxFrameParserState.LOOKING_FOR_START1: - if (byte === UbxFrame.START_BYTE1) { - this.buffer = [byte]; - this.state = UbxFrameParserState.LOOKING_FOR_START2; - } - break; - - case UbxFrameParserState.LOOKING_FOR_START2: - if (byte === UbxFrame.START_BYTE2) { - this.buffer.push(byte); - this.state = UbxFrameParserState.GETTING_MSG_ID; - } else if (byte === UbxFrame.START_BYTE1) { - this.buffer = [byte]; - this.state = UbxFrameParserState.LOOKING_FOR_START2; - } else { - this.state = UbxFrameParserState.LOOKING_FOR_START1; - } - break; - - case UbxFrameParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = UbxFrameParserState.GETTING_LENGTH; - break; - - case UbxFrameParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = UbxFrame.OVERHEAD + this.msg_length; - this.state = UbxFrameParserState.GETTING_PAYLOAD; - break; - - case UbxFrameParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, UbxFrame.HEADER_SIZE, 1, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = UbxFrameParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - static encode(msg_id, msg) { - const output = []; - output.push(UbxFrame.START_BYTE1); - output.push(UbxFrame.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 2); - return new Uint8Array(output); - } - - static validate_packet(buffer) { - if (buffer.length < UbxFrame.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== UbxFrame.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== UbxFrame.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, UbxFrame.HEADER_SIZE, 1, 2); - } -} +/** Parser state alias for backward compatibility */ +const UbxFrameParserState = GenericParserState; module.exports = { UbxFrame, + UbxFrameConfig, UbxFrameParserState, }; diff --git a/src/struct_frame/boilerplate/js/frame_base.js b/src/struct_frame/boilerplate/js/frame_base.js index 3e0164fb..331d15e5 100644 --- a/src/struct_frame/boilerplate/js/frame_base.js +++ b/src/struct_frame/boilerplate/js/frame_base.js @@ -1,5 +1,5 @@ // Automatically generated frame parser base utilities -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. // Frame format type enumeration const FrameFormatType = { @@ -143,6 +143,226 @@ function encode_payload_minimal(output, msgId, msg) { } } +// ============================================================================= +// Generic Frame Parser +// ============================================================================= +// This class provides a reusable frame parser that can be configured +// for different frame formats, reducing code duplication. + +/** Parser state enumeration */ +const GenericParserState = { + LOOKING_FOR_START1: 0, + LOOKING_FOR_START2: 1, + GETTING_MSG_ID: 2, + GETTING_LENGTH: 3, + GETTING_PAYLOAD: 4 +}; + +/** + * Generic frame parser that works with any frame format configuration. + * This class eliminates the need for separate parser classes per format. + */ +class GenericFrameParser { + constructor(config, get_msg_length = undefined) { + this.config = config; + this.get_msg_length = get_msg_length; + this.state = this._getInitialState(); + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + _getInitialState() { + if (this.config.startBytes.length === 0) { + return GenericParserState.GETTING_MSG_ID; + } else { + return GenericParserState.LOOKING_FOR_START1; + } + } + + reset() { + this.state = this._getInitialState(); + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + const startBytes = this.config.startBytes; + const overhead = this.config.headerSize + this.config.footerSize; + + switch (this.state) { + case GenericParserState.LOOKING_FOR_START1: + if (byte === startBytes[0]) { + this.buffer = [byte]; + if (startBytes.length > 1) { + this.state = GenericParserState.LOOKING_FOR_START2; + } else { + this.state = GenericParserState.GETTING_MSG_ID; + } + } + break; + + case GenericParserState.LOOKING_FOR_START2: + if (byte === startBytes[1]) { + this.buffer.push(byte); + this.state = GenericParserState.GETTING_MSG_ID; + } else if (byte === startBytes[0]) { + this.buffer = [byte]; + // Stay in LOOKING_FOR_START2 + } else { + this.state = GenericParserState.LOOKING_FOR_START1; + } + break; + + case GenericParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + if (this.config.hasLength) { + this.state = GenericParserState.GETTING_LENGTH; + } else if (this.get_msg_length) { + const msgLen = this.get_msg_length(byte); + if (msgLen !== undefined) { + this.packet_size = overhead + msgLen; + this.state = GenericParserState.GETTING_PAYLOAD; + } else { + this.state = this._getInitialState(); + } + } else { + this.state = this._getInitialState(); + } + break; + + case GenericParserState.GETTING_LENGTH: + this.buffer.push(byte); + if (this.config.lengthBytes === 1) { + this.msg_length = byte; + this.packet_size = overhead + this.msg_length; + this.state = GenericParserState.GETTING_PAYLOAD; + } else { + // 2-byte length + if (this.buffer.length === startBytes.length + 2) { + this.length_lo = byte; + } else { + this.msg_length = this.length_lo | (byte << 8); + this.packet_size = overhead + this.msg_length; + this.state = GenericParserState.GETTING_PAYLOAD; + } + } + break; + + case GenericParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + if (this.buffer.length >= this.packet_size) { + if (this.config.hasCrc) { + const validationResult = validate_payload_with_crc( + this.buffer, this.config.headerSize, this.config.lengthBytes, startBytes.length); + if (validationResult.valid) { + result.valid = validationResult.valid; + result.msg_id = validationResult.msg_id; + result.msg_len = validationResult.msg_len; + result.msg_data = validationResult.msg_data; + } + } else { + const validationResult = validate_payload_minimal(this.buffer, this.config.headerSize); + result.valid = validationResult.valid; + result.msg_id = validationResult.msg_id; + result.msg_len = validationResult.msg_len; + result.msg_data = validationResult.msg_data; + } + this.state = this._getInitialState(); + } + break; + } + + return result; + } + + /** + * Encode a message using this format (static method) + */ + static encode(config, msg_id, msg) { + const output = []; + + // Add start bytes + for (const startByte of config.startBytes) { + output.push(startByte); + } + + // Use appropriate payload encoding + if (config.hasCrc) { + encode_payload_with_crc(output, msg_id, msg, config.lengthBytes, config.startBytes.length); + } else { + encode_payload_minimal(output, msg_id, msg); + } + + return new Uint8Array(output); + } + + /** + * Validate a complete packet buffer using this format (static method) + */ + static validate_packet(config, buffer) { + const overhead = config.headerSize + config.footerSize; + + if (buffer.length < overhead) { + return createFrameMsgInfo(); + } + + // Check start bytes + for (let i = 0; i < config.startBytes.length; i++) { + if (buffer[i] !== config.startBytes[i]) { + return createFrameMsgInfo(); + } + } + + // Validate payload + if (config.hasCrc) { + return validate_payload_with_crc(buffer, config.headerSize, config.lengthBytes, config.startBytes.length); + } else { + return validate_payload_minimal(buffer, config.headerSize); + } + } +} + +/** + * Create a frame parser class for a specific configuration. + * This factory function provides pre-configured parser classes. + */ +function createFrameParserClass(config) { + // Create a class that extends GenericFrameParser with the config baked in + class ConfiguredFrameParser extends GenericFrameParser { + constructor(get_msg_length = undefined) { + super(config, get_msg_length); + } + + static encode(msg_id, msg) { + return GenericFrameParser.encode(config, msg_id, msg); + } + + static validate_packet(buffer) { + return GenericFrameParser.validate_packet(config, buffer); + } + } + + // Add static properties from config + ConfiguredFrameParser.START_BYTES = config.startBytes; + ConfiguredFrameParser.HEADER_SIZE = config.headerSize; + ConfiguredFrameParser.FOOTER_SIZE = config.footerSize; + ConfiguredFrameParser.OVERHEAD = config.headerSize + config.footerSize; + ConfiguredFrameParser.HAS_LENGTH = config.hasLength; + ConfiguredFrameParser.LENGTH_BYTES = config.lengthBytes; + ConfiguredFrameParser.HAS_CRC = config.hasCrc; + ConfiguredFrameParser.CONFIG = config; + + return ConfiguredFrameParser; +} + module.exports = { FrameFormatType, fletcher_checksum, @@ -151,4 +371,7 @@ module.exports = { validate_payload_minimal, encode_payload_with_crc, encode_payload_minimal, + GenericParserState, + GenericFrameParser, + createFrameParserClass, }; diff --git a/src/struct_frame/boilerplate/js/index.js b/src/struct_frame/boilerplate/js/index.js index 752867ed..7828c776 100644 --- a/src/struct_frame/boilerplate/js/index.js +++ b/src/struct_frame/boilerplate/js/index.js @@ -1,5 +1,5 @@ // Automatically generated frame parser package -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. // Base utilities const frameBase = require('./frame_base'); diff --git a/src/struct_frame/boilerplate/py/__init__.py b/src/struct_frame/boilerplate/py/__init__.py index d5196f34..d2abe5e1 100644 --- a/src/struct_frame/boilerplate/py/__init__.py +++ b/src/struct_frame/boilerplate/py/__init__.py @@ -1,11 +1,17 @@ # Automatically generated frame parser package -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -# Base utilities +# Base utilities and generic parser infrastructure from .frame_base import ( FrameFormatType, FrameMsgInfo, fletcher_checksum, + # Configuration interface for code reuse + FrameParserConfig, + # Generic parser class (use create_frame_parser_class for type-safe wrappers) + GenericFrameParser, + GenericParserState, + create_frame_parser_class, # Shared payload parsing functions validate_payload_with_crc, validate_payload_minimal, @@ -13,29 +19,29 @@ encode_payload_minimal, ) -# Individual frame format parsers -from .tiny_minimal import TinyMinimal, TinyMinimalParserState -from .tiny_default import TinyDefault, TinyDefaultParserState -from .tiny_extended_msg_ids import TinyExtendedMsgIds, TinyExtendedMsgIdsParserState -from .tiny_extended_length import TinyExtendedLength, TinyExtendedLengthParserState -from .tiny_extended import TinyExtended, TinyExtendedParserState -from .tiny_sys_comp import TinySysComp, TinySysCompParserState -from .tiny_seq import TinySeq, TinySeqParserState -from .tiny_multi_system_stream import TinyMultiSystemStream, TinyMultiSystemStreamParserState -from .tiny_extended_multi_system_stream import TinyExtendedMultiSystemStream, TinyExtendedMultiSystemStreamParserState -from .basic_minimal import BasicMinimal, BasicMinimalParserState -from .basic_default import BasicDefault, BasicDefaultParserState -from .basic_extended_msg_ids import BasicExtendedMsgIds, BasicExtendedMsgIdsParserState -from .basic_extended_length import BasicExtendedLength, BasicExtendedLengthParserState -from .basic_extended import BasicExtended, BasicExtendedParserState -from .basic_sys_comp import BasicSysComp, BasicSysCompParserState -from .basic_seq import BasicSeq, BasicSeqParserState -from .basic_multi_system_stream import BasicMultiSystemStream, BasicMultiSystemStreamParserState -from .basic_extended_multi_system_stream import BasicExtendedMultiSystemStream, BasicExtendedMultiSystemStreamParserState -from .ubx_frame import UbxFrame, UbxFrameParserState -from .mavlink_v1_frame import MavlinkV1Frame, MavlinkV1FrameParserState -from .mavlink_v2_frame import MavlinkV2Frame, MavlinkV2FrameParserState -from .frame_format_config import FrameFormatConfig, FrameFormatConfigParserState +# Individual frame format parsers (configuration-based) +from .tiny_minimal import TinyMinimal, TinyMinimalConfig, TinyMinimalParserState +from .tiny_default import TinyDefault, TinyDefaultConfig, TinyDefaultParserState +from .tiny_extended_msg_ids import TinyExtendedMsgIds, TinyExtendedMsgIdsConfig, TinyExtendedMsgIdsParserState +from .tiny_extended_length import TinyExtendedLength, TinyExtendedLengthConfig, TinyExtendedLengthParserState +from .tiny_extended import TinyExtended, TinyExtendedConfig, TinyExtendedParserState +from .tiny_sys_comp import TinySysComp, TinySysCompConfig, TinySysCompParserState +from .tiny_seq import TinySeq, TinySeqConfig, TinySeqParserState +from .tiny_multi_system_stream import TinyMultiSystemStream, TinyMultiSystemStreamConfig, TinyMultiSystemStreamParserState +from .tiny_extended_multi_system_stream import TinyExtendedMultiSystemStream, TinyExtendedMultiSystemStreamConfig, TinyExtendedMultiSystemStreamParserState +from .basic_minimal import BasicMinimal, BasicMinimalConfig, BasicMinimalParserState +from .basic_default import BasicDefault, BasicDefaultConfig, BasicDefaultParserState +from .basic_extended_msg_ids import BasicExtendedMsgIds, BasicExtendedMsgIdsConfig, BasicExtendedMsgIdsParserState +from .basic_extended_length import BasicExtendedLength, BasicExtendedLengthConfig, BasicExtendedLengthParserState +from .basic_extended import BasicExtended, BasicExtendedConfig, BasicExtendedParserState +from .basic_sys_comp import BasicSysComp, BasicSysCompConfig, BasicSysCompParserState +from .basic_seq import BasicSeq, BasicSeqConfig, BasicSeqParserState +from .basic_multi_system_stream import BasicMultiSystemStream, BasicMultiSystemStreamConfig, BasicMultiSystemStreamParserState +from .basic_extended_multi_system_stream import BasicExtendedMultiSystemStream, BasicExtendedMultiSystemStreamConfig, BasicExtendedMultiSystemStreamParserState +from .ubx_frame import UbxFrame, UbxFrameConfig, UbxFrameParserState +from .mavlink_v1_frame import MavlinkV1Frame, MavlinkV1FrameConfig, MavlinkV1FrameParserState +from .mavlink_v2_frame import MavlinkV2Frame, MavlinkV2FrameConfig, MavlinkV2FrameParserState +from .frame_format_config import FrameFormatConfig, FrameFormatConfigConfig, FrameFormatConfigParserState # Re-export all frame formats __all__ = [ @@ -43,6 +49,11 @@ "FrameFormatType", "FrameMsgInfo", "fletcher_checksum", + # Configuration and generic parser + "FrameParserConfig", + "GenericFrameParser", + "GenericParserState", + "create_frame_parser_class", # Shared payload parsing functions "validate_payload_with_crc", "validate_payload_minimal", @@ -50,47 +61,69 @@ "encode_payload_minimal", # Frame formats "TinyMinimal", + "TinyMinimalConfig", "TinyMinimalParserState", "TinyDefault", + "TinyDefaultConfig", "TinyDefaultParserState", "TinyExtendedMsgIds", + "TinyExtendedMsgIdsConfig", "TinyExtendedMsgIdsParserState", "TinyExtendedLength", + "TinyExtendedLengthConfig", "TinyExtendedLengthParserState", "TinyExtended", + "TinyExtendedConfig", "TinyExtendedParserState", "TinySysComp", + "TinySysCompConfig", "TinySysCompParserState", "TinySeq", + "TinySeqConfig", "TinySeqParserState", "TinyMultiSystemStream", + "TinyMultiSystemStreamConfig", "TinyMultiSystemStreamParserState", "TinyExtendedMultiSystemStream", + "TinyExtendedMultiSystemStreamConfig", "TinyExtendedMultiSystemStreamParserState", "BasicMinimal", + "BasicMinimalConfig", "BasicMinimalParserState", "BasicDefault", + "BasicDefaultConfig", "BasicDefaultParserState", "BasicExtendedMsgIds", + "BasicExtendedMsgIdsConfig", "BasicExtendedMsgIdsParserState", "BasicExtendedLength", + "BasicExtendedLengthConfig", "BasicExtendedLengthParserState", "BasicExtended", + "BasicExtendedConfig", "BasicExtendedParserState", "BasicSysComp", + "BasicSysCompConfig", "BasicSysCompParserState", "BasicSeq", + "BasicSeqConfig", "BasicSeqParserState", "BasicMultiSystemStream", + "BasicMultiSystemStreamConfig", "BasicMultiSystemStreamParserState", "BasicExtendedMultiSystemStream", + "BasicExtendedMultiSystemStreamConfig", "BasicExtendedMultiSystemStreamParserState", "UbxFrame", + "UbxFrameConfig", "UbxFrameParserState", "MavlinkV1Frame", + "MavlinkV1FrameConfig", "MavlinkV1FrameParserState", "MavlinkV2Frame", + "MavlinkV2FrameConfig", "MavlinkV2FrameParserState", "FrameFormatConfig", + "FrameFormatConfigConfig", "FrameFormatConfigParserState", ] diff --git a/src/struct_frame/boilerplate/py/basic_default.py b/src/struct_frame/boilerplate/py/basic_default.py index c2636701..4df8b5b5 100644 --- a/src/struct_frame/boilerplate/py/basic_default.py +++ b/src/struct_frame/boilerplate/py/basic_default.py @@ -1,144 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# BasicDefault Frame Format +# BasicDefault Frame Format Configuration # ============================================================================= -class BasicDefaultParserState(Enum): - LOOKING_FOR_START1 = 0 - LOOKING_FOR_START2 = 1 - GETTING_MSG_ID = 2 - GETTING_LENGTH = 3 - GETTING_PAYLOAD = 4 - - -class BasicDefault: - """ - BasicDefault - Frame format parser and encoder - - Format: [START_BYTE1=0x90] [START_BYTE2=0x71] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE1 = 0x90 - START_BYTE2 = 0x71 - HEADER_SIZE = 4 - FOOTER_SIZE = 2 - OVERHEAD = 6 - LENGTH_BYTES = 1 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the BasicDefault parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = BasicDefaultParserState.LOOKING_FOR_START1 - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == BasicDefaultParserState.LOOKING_FOR_START1: - if byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicDefaultParserState.LOOKING_FOR_START2 - - elif self.state == BasicDefaultParserState.LOOKING_FOR_START2: - if byte == self.START_BYTE2: - self.buffer.append(byte) - self.state = BasicDefaultParserState.GETTING_MSG_ID - elif byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicDefaultParserState.LOOKING_FOR_START2 - else: - self.state = BasicDefaultParserState.LOOKING_FOR_START1 - - elif self.state == BasicDefaultParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = BasicDefaultParserState.GETTING_LENGTH - - elif self.state == BasicDefaultParserState.GETTING_LENGTH: - self.buffer.append(byte) - self.msg_length = byte - self.packet_size = self.OVERHEAD + self.msg_length - self.state = BasicDefaultParserState.GETTING_PAYLOAD - - elif self.state == BasicDefaultParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 1, 2) - self.state = BasicDefaultParserState.LOOKING_FOR_START1 - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with BasicDefault format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE1) - output.append(self.START_BYTE2) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 2) - return bytes(output) +# Configuration for BasicDefault frame format +BasicDefaultConfig = FrameParserConfig( + name='BasicDefault', + start_bytes=(0x90, 0x71), + header_size=4, + footer_size=2, + has_length=True, + length_bytes=1, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +BasicDefault - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete BasicDefault packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < BasicDefault.OVERHEAD: - return FrameMsgInfo() +Format: [START_BYTE1=0x90] [START_BYTE2=0x71] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - if buffer[0] != BasicDefault.START_BYTE1: - return FrameMsgInfo() - if buffer[1] != BasicDefault.START_BYTE2: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +BasicDefault = create_frame_parser_class(BasicDefaultConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicDefault.HEADER_SIZE, 1, 2) +# Parser state alias for backward compatibility +BasicDefaultParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/basic_extended.py b/src/struct_frame/boilerplate/py/basic_extended.py index 263e547d..a692d09f 100644 --- a/src/struct_frame/boilerplate/py/basic_extended.py +++ b/src/struct_frame/boilerplate/py/basic_extended.py @@ -1,148 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# BasicExtended Frame Format +# BasicExtended Frame Format Configuration # ============================================================================= -class BasicExtendedParserState(Enum): - LOOKING_FOR_START1 = 0 - LOOKING_FOR_START2 = 1 - GETTING_MSG_ID = 2 - GETTING_LENGTH = 3 - GETTING_PAYLOAD = 4 - - -class BasicExtended: - """ - BasicExtended - Frame format parser and encoder - - Format: [START_BYTE1=0x90] [START_BYTE2=0x74] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE1 = 0x90 - START_BYTE2 = 0x74 - HEADER_SIZE = 6 - FOOTER_SIZE = 2 - OVERHEAD = 8 - LENGTH_BYTES = 2 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the BasicExtended parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = BasicExtendedParserState.LOOKING_FOR_START1 - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - self.length_lo = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == BasicExtendedParserState.LOOKING_FOR_START1: - if byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicExtendedParserState.LOOKING_FOR_START2 - - elif self.state == BasicExtendedParserState.LOOKING_FOR_START2: - if byte == self.START_BYTE2: - self.buffer.append(byte) - self.state = BasicExtendedParserState.GETTING_MSG_ID - elif byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicExtendedParserState.LOOKING_FOR_START2 - else: - self.state = BasicExtendedParserState.LOOKING_FOR_START1 - - elif self.state == BasicExtendedParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = BasicExtendedParserState.GETTING_LENGTH - - elif self.state == BasicExtendedParserState.GETTING_LENGTH: - self.buffer.append(byte) - if len(self.buffer) == 4: - self.length_lo = byte - else: - self.msg_length = self.length_lo | (byte << 8) - self.packet_size = self.OVERHEAD + self.msg_length - self.state = BasicExtendedParserState.GETTING_PAYLOAD - - elif self.state == BasicExtendedParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 2, 2) - self.state = BasicExtendedParserState.LOOKING_FOR_START1 - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with BasicExtended format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE1) - output.append(self.START_BYTE2) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 2, 2) - return bytes(output) +# Configuration for BasicExtended frame format +BasicExtendedConfig = FrameParserConfig( + name='BasicExtended', + start_bytes=(0x90, 0x74), + header_size=6, + footer_size=2, + has_length=True, + length_bytes=2, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +BasicExtended - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete BasicExtended packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < BasicExtended.OVERHEAD: - return FrameMsgInfo() +Format: [START_BYTE1=0x90] [START_BYTE2=0x74] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] - if buffer[0] != BasicExtended.START_BYTE1: - return FrameMsgInfo() - if buffer[1] != BasicExtended.START_BYTE2: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +BasicExtended = create_frame_parser_class(BasicExtendedConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicExtended.HEADER_SIZE, 2, 2) +# Parser state alias for backward compatibility +BasicExtendedParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/basic_extended_length.py b/src/struct_frame/boilerplate/py/basic_extended_length.py index e71100f4..fc0a8ccd 100644 --- a/src/struct_frame/boilerplate/py/basic_extended_length.py +++ b/src/struct_frame/boilerplate/py/basic_extended_length.py @@ -1,148 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# BasicExtendedLength Frame Format +# BasicExtendedLength Frame Format Configuration # ============================================================================= -class BasicExtendedLengthParserState(Enum): - LOOKING_FOR_START1 = 0 - LOOKING_FOR_START2 = 1 - GETTING_MSG_ID = 2 - GETTING_LENGTH = 3 - GETTING_PAYLOAD = 4 - - -class BasicExtendedLength: - """ - BasicExtendedLength - Frame format parser and encoder - - Format: [START_BYTE1=0x90] [START_BYTE2=0x73] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE1 = 0x90 - START_BYTE2 = 0x73 - HEADER_SIZE = 5 - FOOTER_SIZE = 2 - OVERHEAD = 7 - LENGTH_BYTES = 2 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the BasicExtendedLength parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = BasicExtendedLengthParserState.LOOKING_FOR_START1 - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - self.length_lo = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == BasicExtendedLengthParserState.LOOKING_FOR_START1: - if byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicExtendedLengthParserState.LOOKING_FOR_START2 - - elif self.state == BasicExtendedLengthParserState.LOOKING_FOR_START2: - if byte == self.START_BYTE2: - self.buffer.append(byte) - self.state = BasicExtendedLengthParserState.GETTING_MSG_ID - elif byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicExtendedLengthParserState.LOOKING_FOR_START2 - else: - self.state = BasicExtendedLengthParserState.LOOKING_FOR_START1 - - elif self.state == BasicExtendedLengthParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = BasicExtendedLengthParserState.GETTING_LENGTH - - elif self.state == BasicExtendedLengthParserState.GETTING_LENGTH: - self.buffer.append(byte) - if len(self.buffer) == 4: - self.length_lo = byte - else: - self.msg_length = self.length_lo | (byte << 8) - self.packet_size = self.OVERHEAD + self.msg_length - self.state = BasicExtendedLengthParserState.GETTING_PAYLOAD - - elif self.state == BasicExtendedLengthParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 2, 2) - self.state = BasicExtendedLengthParserState.LOOKING_FOR_START1 - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with BasicExtendedLength format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE1) - output.append(self.START_BYTE2) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 2, 2) - return bytes(output) +# Configuration for BasicExtendedLength frame format +BasicExtendedLengthConfig = FrameParserConfig( + name='BasicExtendedLength', + start_bytes=(0x90, 0x73), + header_size=5, + footer_size=2, + has_length=True, + length_bytes=2, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +BasicExtendedLength - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete BasicExtendedLength packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < BasicExtendedLength.OVERHEAD: - return FrameMsgInfo() +Format: [START_BYTE1=0x90] [START_BYTE2=0x73] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] - if buffer[0] != BasicExtendedLength.START_BYTE1: - return FrameMsgInfo() - if buffer[1] != BasicExtendedLength.START_BYTE2: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +BasicExtendedLength = create_frame_parser_class(BasicExtendedLengthConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicExtendedLength.HEADER_SIZE, 2, 2) +# Parser state alias for backward compatibility +BasicExtendedLengthParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/basic_extended_msg_ids.py b/src/struct_frame/boilerplate/py/basic_extended_msg_ids.py index db795a6e..5ca34d0c 100644 --- a/src/struct_frame/boilerplate/py/basic_extended_msg_ids.py +++ b/src/struct_frame/boilerplate/py/basic_extended_msg_ids.py @@ -1,144 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# BasicExtendedMsgIds Frame Format +# BasicExtendedMsgIds Frame Format Configuration # ============================================================================= -class BasicExtendedMsgIdsParserState(Enum): - LOOKING_FOR_START1 = 0 - LOOKING_FOR_START2 = 1 - GETTING_MSG_ID = 2 - GETTING_LENGTH = 3 - GETTING_PAYLOAD = 4 - - -class BasicExtendedMsgIds: - """ - BasicExtendedMsgIds - Frame format parser and encoder - - Format: [START_BYTE1=0x90] [START_BYTE2=0x72] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE1 = 0x90 - START_BYTE2 = 0x72 - HEADER_SIZE = 5 - FOOTER_SIZE = 2 - OVERHEAD = 7 - LENGTH_BYTES = 1 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the BasicExtendedMsgIds parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1 - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == BasicExtendedMsgIdsParserState.LOOKING_FOR_START1: - if byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START2 - - elif self.state == BasicExtendedMsgIdsParserState.LOOKING_FOR_START2: - if byte == self.START_BYTE2: - self.buffer.append(byte) - self.state = BasicExtendedMsgIdsParserState.GETTING_MSG_ID - elif byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START2 - else: - self.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1 - - elif self.state == BasicExtendedMsgIdsParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = BasicExtendedMsgIdsParserState.GETTING_LENGTH - - elif self.state == BasicExtendedMsgIdsParserState.GETTING_LENGTH: - self.buffer.append(byte) - self.msg_length = byte - self.packet_size = self.OVERHEAD + self.msg_length - self.state = BasicExtendedMsgIdsParserState.GETTING_PAYLOAD - - elif self.state == BasicExtendedMsgIdsParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 1, 2) - self.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1 - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with BasicExtendedMsgIds format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE1) - output.append(self.START_BYTE2) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 2) - return bytes(output) +# Configuration for BasicExtendedMsgIds frame format +BasicExtendedMsgIdsConfig = FrameParserConfig( + name='BasicExtendedMsgIds', + start_bytes=(0x90, 0x72), + header_size=5, + footer_size=2, + has_length=True, + length_bytes=1, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +BasicExtendedMsgIds - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete BasicExtendedMsgIds packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < BasicExtendedMsgIds.OVERHEAD: - return FrameMsgInfo() +Format: [START_BYTE1=0x90] [START_BYTE2=0x72] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - if buffer[0] != BasicExtendedMsgIds.START_BYTE1: - return FrameMsgInfo() - if buffer[1] != BasicExtendedMsgIds.START_BYTE2: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +BasicExtendedMsgIds = create_frame_parser_class(BasicExtendedMsgIdsConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicExtendedMsgIds.HEADER_SIZE, 1, 2) +# Parser state alias for backward compatibility +BasicExtendedMsgIdsParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/basic_extended_multi_system_stream.py b/src/struct_frame/boilerplate/py/basic_extended_multi_system_stream.py index 8648e728..800e93b1 100644 --- a/src/struct_frame/boilerplate/py/basic_extended_multi_system_stream.py +++ b/src/struct_frame/boilerplate/py/basic_extended_multi_system_stream.py @@ -1,148 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# BasicExtendedMultiSystemStream Frame Format +# BasicExtendedMultiSystemStream Frame Format Configuration # ============================================================================= -class BasicExtendedMultiSystemStreamParserState(Enum): - LOOKING_FOR_START1 = 0 - LOOKING_FOR_START2 = 1 - GETTING_MSG_ID = 2 - GETTING_LENGTH = 3 - GETTING_PAYLOAD = 4 - - -class BasicExtendedMultiSystemStream: - """ - BasicExtendedMultiSystemStream - Frame format parser and encoder - - Format: [START_BYTE1=0x90] [START_BYTE2=0x78] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE1 = 0x90 - START_BYTE2 = 0x78 - HEADER_SIZE = 9 - FOOTER_SIZE = 2 - OVERHEAD = 11 - LENGTH_BYTES = 2 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the BasicExtendedMultiSystemStream parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1 - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - self.length_lo = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1: - if byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START2 - - elif self.state == BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START2: - if byte == self.START_BYTE2: - self.buffer.append(byte) - self.state = BasicExtendedMultiSystemStreamParserState.GETTING_MSG_ID - elif byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START2 - else: - self.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1 - - elif self.state == BasicExtendedMultiSystemStreamParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = BasicExtendedMultiSystemStreamParserState.GETTING_LENGTH - - elif self.state == BasicExtendedMultiSystemStreamParserState.GETTING_LENGTH: - self.buffer.append(byte) - if len(self.buffer) == 4: - self.length_lo = byte - else: - self.msg_length = self.length_lo | (byte << 8) - self.packet_size = self.OVERHEAD + self.msg_length - self.state = BasicExtendedMultiSystemStreamParserState.GETTING_PAYLOAD - - elif self.state == BasicExtendedMultiSystemStreamParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 2, 2) - self.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1 - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with BasicExtendedMultiSystemStream format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE1) - output.append(self.START_BYTE2) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 2, 2) - return bytes(output) +# Configuration for BasicExtendedMultiSystemStream frame format +BasicExtendedMultiSystemStreamConfig = FrameParserConfig( + name='BasicExtendedMultiSystemStream', + start_bytes=(0x90, 0x78), + header_size=9, + footer_size=2, + has_length=True, + length_bytes=2, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +BasicExtendedMultiSystemStream - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete BasicExtendedMultiSystemStream packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < BasicExtendedMultiSystemStream.OVERHEAD: - return FrameMsgInfo() +Format: [START_BYTE1=0x90] [START_BYTE2=0x78] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] - if buffer[0] != BasicExtendedMultiSystemStream.START_BYTE1: - return FrameMsgInfo() - if buffer[1] != BasicExtendedMultiSystemStream.START_BYTE2: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +BasicExtendedMultiSystemStream = create_frame_parser_class(BasicExtendedMultiSystemStreamConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicExtendedMultiSystemStream.HEADER_SIZE, 2, 2) +# Parser state alias for backward compatibility +BasicExtendedMultiSystemStreamParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/basic_minimal.py b/src/struct_frame/boilerplate/py/basic_minimal.py index e68be2b8..5fed738b 100644 --- a/src/struct_frame/boilerplate/py/basic_minimal.py +++ b/src/struct_frame/boilerplate/py/basic_minimal.py @@ -1,143 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# BasicMinimal Frame Format +# BasicMinimal Frame Format Configuration # ============================================================================= -class BasicMinimalParserState(Enum): - LOOKING_FOR_START1 = 0 - LOOKING_FOR_START2 = 1 - GETTING_MSG_ID = 2 - GETTING_PAYLOAD = 3 - - -class BasicMinimal: - """ - BasicMinimal - Frame format parser and encoder - - Format: [START_BYTE1=0x90] [START_BYTE2=0x70] [MSG_ID] [MSG...] - """ - - START_BYTE1 = 0x90 - START_BYTE2 = 0x70 - HEADER_SIZE = 3 - FOOTER_SIZE = 0 - OVERHEAD = 3 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the BasicMinimal parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = BasicMinimalParserState.LOOKING_FOR_START1 - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == BasicMinimalParserState.LOOKING_FOR_START1: - if byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicMinimalParserState.LOOKING_FOR_START2 - - elif self.state == BasicMinimalParserState.LOOKING_FOR_START2: - if byte == self.START_BYTE2: - self.buffer.append(byte) - self.state = BasicMinimalParserState.GETTING_MSG_ID - elif byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicMinimalParserState.LOOKING_FOR_START2 - else: - self.state = BasicMinimalParserState.LOOKING_FOR_START1 - - elif self.state == BasicMinimalParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - if self.get_msg_length: - msg_length = self.get_msg_length(byte) - if msg_length is not None: - self.packet_size = self.OVERHEAD + msg_length - self.state = BasicMinimalParserState.GETTING_PAYLOAD - else: - self.state = BasicMinimalParserState.LOOKING_FOR_START1 - else: - self.state = BasicMinimalParserState.LOOKING_FOR_START1 - - elif self.state == BasicMinimalParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared minimal payload validation - result = validate_payload_minimal(self.buffer, self.HEADER_SIZE) - self.state = BasicMinimalParserState.LOOKING_FOR_START1 - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with BasicMinimal format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE1) - output.append(self.START_BYTE2) - # Use shared minimal payload encoding - encode_payload_minimal(output, msg_id, msg) - return bytes(output) +# Configuration for BasicMinimal frame format +BasicMinimalConfig = FrameParserConfig( + name='BasicMinimal', + start_bytes=(0x90, 0x70), + header_size=3, + footer_size=0, + has_length=False, + length_bytes=0, + has_crc=False, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +BasicMinimal - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete BasicMinimal packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < BasicMinimal.OVERHEAD: - return FrameMsgInfo() +Format: [START_BYTE1=0x90] [START_BYTE2=0x70] [MSG_ID] [MSG...] - if buffer[0] != BasicMinimal.START_BYTE1: - return FrameMsgInfo() - if buffer[1] != BasicMinimal.START_BYTE2: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +BasicMinimal = create_frame_parser_class(BasicMinimalConfig) - # Use shared minimal payload validation - return validate_payload_minimal(buffer, BasicMinimal.HEADER_SIZE) +# Parser state alias for backward compatibility +BasicMinimalParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/basic_multi_system_stream.py b/src/struct_frame/boilerplate/py/basic_multi_system_stream.py index e665fa0c..99ecf897 100644 --- a/src/struct_frame/boilerplate/py/basic_multi_system_stream.py +++ b/src/struct_frame/boilerplate/py/basic_multi_system_stream.py @@ -1,144 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# BasicMultiSystemStream Frame Format +# BasicMultiSystemStream Frame Format Configuration # ============================================================================= -class BasicMultiSystemStreamParserState(Enum): - LOOKING_FOR_START1 = 0 - LOOKING_FOR_START2 = 1 - GETTING_MSG_ID = 2 - GETTING_LENGTH = 3 - GETTING_PAYLOAD = 4 - - -class BasicMultiSystemStream: - """ - BasicMultiSystemStream - Frame format parser and encoder - - Format: [START_BYTE1=0x90] [START_BYTE2=0x77] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE1 = 0x90 - START_BYTE2 = 0x77 - HEADER_SIZE = 7 - FOOTER_SIZE = 2 - OVERHEAD = 9 - LENGTH_BYTES = 1 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the BasicMultiSystemStream parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1 - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == BasicMultiSystemStreamParserState.LOOKING_FOR_START1: - if byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START2 - - elif self.state == BasicMultiSystemStreamParserState.LOOKING_FOR_START2: - if byte == self.START_BYTE2: - self.buffer.append(byte) - self.state = BasicMultiSystemStreamParserState.GETTING_MSG_ID - elif byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START2 - else: - self.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1 - - elif self.state == BasicMultiSystemStreamParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = BasicMultiSystemStreamParserState.GETTING_LENGTH - - elif self.state == BasicMultiSystemStreamParserState.GETTING_LENGTH: - self.buffer.append(byte) - self.msg_length = byte - self.packet_size = self.OVERHEAD + self.msg_length - self.state = BasicMultiSystemStreamParserState.GETTING_PAYLOAD - - elif self.state == BasicMultiSystemStreamParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 1, 2) - self.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1 - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with BasicMultiSystemStream format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE1) - output.append(self.START_BYTE2) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 2) - return bytes(output) +# Configuration for BasicMultiSystemStream frame format +BasicMultiSystemStreamConfig = FrameParserConfig( + name='BasicMultiSystemStream', + start_bytes=(0x90, 0x77), + header_size=7, + footer_size=2, + has_length=True, + length_bytes=1, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +BasicMultiSystemStream - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete BasicMultiSystemStream packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < BasicMultiSystemStream.OVERHEAD: - return FrameMsgInfo() +Format: [START_BYTE1=0x90] [START_BYTE2=0x77] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - if buffer[0] != BasicMultiSystemStream.START_BYTE1: - return FrameMsgInfo() - if buffer[1] != BasicMultiSystemStream.START_BYTE2: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +BasicMultiSystemStream = create_frame_parser_class(BasicMultiSystemStreamConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicMultiSystemStream.HEADER_SIZE, 1, 2) +# Parser state alias for backward compatibility +BasicMultiSystemStreamParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/basic_seq.py b/src/struct_frame/boilerplate/py/basic_seq.py index 9bc20793..ab02dfa8 100644 --- a/src/struct_frame/boilerplate/py/basic_seq.py +++ b/src/struct_frame/boilerplate/py/basic_seq.py @@ -1,144 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# BasicSeq Frame Format +# BasicSeq Frame Format Configuration # ============================================================================= -class BasicSeqParserState(Enum): - LOOKING_FOR_START1 = 0 - LOOKING_FOR_START2 = 1 - GETTING_MSG_ID = 2 - GETTING_LENGTH = 3 - GETTING_PAYLOAD = 4 - - -class BasicSeq: - """ - BasicSeq - Frame format parser and encoder - - Format: [START_BYTE1=0x90] [START_BYTE2=0x76] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE1 = 0x90 - START_BYTE2 = 0x76 - HEADER_SIZE = 5 - FOOTER_SIZE = 2 - OVERHEAD = 7 - LENGTH_BYTES = 1 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the BasicSeq parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = BasicSeqParserState.LOOKING_FOR_START1 - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == BasicSeqParserState.LOOKING_FOR_START1: - if byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicSeqParserState.LOOKING_FOR_START2 - - elif self.state == BasicSeqParserState.LOOKING_FOR_START2: - if byte == self.START_BYTE2: - self.buffer.append(byte) - self.state = BasicSeqParserState.GETTING_MSG_ID - elif byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicSeqParserState.LOOKING_FOR_START2 - else: - self.state = BasicSeqParserState.LOOKING_FOR_START1 - - elif self.state == BasicSeqParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = BasicSeqParserState.GETTING_LENGTH - - elif self.state == BasicSeqParserState.GETTING_LENGTH: - self.buffer.append(byte) - self.msg_length = byte - self.packet_size = self.OVERHEAD + self.msg_length - self.state = BasicSeqParserState.GETTING_PAYLOAD - - elif self.state == BasicSeqParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 1, 2) - self.state = BasicSeqParserState.LOOKING_FOR_START1 - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with BasicSeq format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE1) - output.append(self.START_BYTE2) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 2) - return bytes(output) +# Configuration for BasicSeq frame format +BasicSeqConfig = FrameParserConfig( + name='BasicSeq', + start_bytes=(0x90, 0x76), + header_size=5, + footer_size=2, + has_length=True, + length_bytes=1, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +BasicSeq - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete BasicSeq packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < BasicSeq.OVERHEAD: - return FrameMsgInfo() +Format: [START_BYTE1=0x90] [START_BYTE2=0x76] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - if buffer[0] != BasicSeq.START_BYTE1: - return FrameMsgInfo() - if buffer[1] != BasicSeq.START_BYTE2: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +BasicSeq = create_frame_parser_class(BasicSeqConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicSeq.HEADER_SIZE, 1, 2) +# Parser state alias for backward compatibility +BasicSeqParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/basic_sys_comp.py b/src/struct_frame/boilerplate/py/basic_sys_comp.py index 35bccbc8..ea6b6f7d 100644 --- a/src/struct_frame/boilerplate/py/basic_sys_comp.py +++ b/src/struct_frame/boilerplate/py/basic_sys_comp.py @@ -1,144 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# BasicSysComp Frame Format +# BasicSysComp Frame Format Configuration # ============================================================================= -class BasicSysCompParserState(Enum): - LOOKING_FOR_START1 = 0 - LOOKING_FOR_START2 = 1 - GETTING_MSG_ID = 2 - GETTING_LENGTH = 3 - GETTING_PAYLOAD = 4 - - -class BasicSysComp: - """ - BasicSysComp - Frame format parser and encoder - - Format: [START_BYTE1=0x90] [START_BYTE2=0x75] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE1 = 0x90 - START_BYTE2 = 0x75 - HEADER_SIZE = 6 - FOOTER_SIZE = 2 - OVERHEAD = 8 - LENGTH_BYTES = 1 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the BasicSysComp parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = BasicSysCompParserState.LOOKING_FOR_START1 - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == BasicSysCompParserState.LOOKING_FOR_START1: - if byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicSysCompParserState.LOOKING_FOR_START2 - - elif self.state == BasicSysCompParserState.LOOKING_FOR_START2: - if byte == self.START_BYTE2: - self.buffer.append(byte) - self.state = BasicSysCompParserState.GETTING_MSG_ID - elif byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicSysCompParserState.LOOKING_FOR_START2 - else: - self.state = BasicSysCompParserState.LOOKING_FOR_START1 - - elif self.state == BasicSysCompParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = BasicSysCompParserState.GETTING_LENGTH - - elif self.state == BasicSysCompParserState.GETTING_LENGTH: - self.buffer.append(byte) - self.msg_length = byte - self.packet_size = self.OVERHEAD + self.msg_length - self.state = BasicSysCompParserState.GETTING_PAYLOAD - - elif self.state == BasicSysCompParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 1, 2) - self.state = BasicSysCompParserState.LOOKING_FOR_START1 - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with BasicSysComp format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE1) - output.append(self.START_BYTE2) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 2) - return bytes(output) +# Configuration for BasicSysComp frame format +BasicSysCompConfig = FrameParserConfig( + name='BasicSysComp', + start_bytes=(0x90, 0x75), + header_size=6, + footer_size=2, + has_length=True, + length_bytes=1, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +BasicSysComp - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete BasicSysComp packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < BasicSysComp.OVERHEAD: - return FrameMsgInfo() +Format: [START_BYTE1=0x90] [START_BYTE2=0x75] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - if buffer[0] != BasicSysComp.START_BYTE1: - return FrameMsgInfo() - if buffer[1] != BasicSysComp.START_BYTE2: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +BasicSysComp = create_frame_parser_class(BasicSysCompConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicSysComp.HEADER_SIZE, 1, 2) +# Parser state alias for backward compatibility +BasicSysCompParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/frame_base.py b/src/struct_frame/boilerplate/py/frame_base.py index 5a32e6e7..92370160 100644 --- a/src/struct_frame/boilerplate/py/frame_base.py +++ b/src/struct_frame/boilerplate/py/frame_base.py @@ -1,8 +1,8 @@ # Automatically generated frame parser base utilities -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. from enum import Enum -from typing import List, Tuple, Union +from typing import Callable, List, Tuple, Union from dataclasses import dataclass # Frame format type enumeration @@ -164,3 +164,218 @@ def encode_payload_minimal(output: list, msg_id: int, msg: bytes) -> None: """ output.append(msg_id) output.extend(msg) + + +# ============================================================================= +# Frame Parser Configuration +# ============================================================================= + +@dataclass +class FrameParserConfig: + """ + Configuration interface for frame format parsers. + This allows code reuse through configuration instead of code generation. + """ + name: str + start_bytes: Tuple[int, ...] + header_size: int + footer_size: int + has_length: bool + length_bytes: int + has_crc: bool + + +# ============================================================================= +# Generic Frame Parser +# ============================================================================= +# This class provides a reusable frame parser that can be configured +# for different frame formats, reducing code duplication. + +class GenericParserState(Enum): + """Parser state enumeration""" + LOOKING_FOR_START1 = 0 + LOOKING_FOR_START2 = 1 + GETTING_MSG_ID = 2 + GETTING_LENGTH = 3 + GETTING_PAYLOAD = 4 + + +class GenericFrameParser: + """ + Generic frame parser that works with any frame format configuration. + This class eliminates the need for separate parser classes per format. + """ + + def __init__(self, config: FrameParserConfig, get_msg_length: Callable[[int], int] = None): + self.config = config + self.get_msg_length = get_msg_length + self.reset() + + def _get_initial_state(self) -> GenericParserState: + if len(self.config.start_bytes) == 0: + return GenericParserState.GETTING_MSG_ID + else: + return GenericParserState.LOOKING_FOR_START1 + + def reset(self): + """Reset parser state""" + self.state = self._get_initial_state() + self.buffer = [] + self.packet_size = 0 + self.msg_id = 0 + self.msg_length = 0 + self.length_lo = 0 + + def parse_byte(self, byte: int) -> FrameMsgInfo: + """ + Parse a single byte + + Returns: + FrameMsgInfo with valid=True when a complete valid message is received + """ + result = FrameMsgInfo() + start_bytes = self.config.start_bytes + overhead = self.config.header_size + self.config.footer_size + + if self.state == GenericParserState.LOOKING_FOR_START1: + if byte == start_bytes[0]: + self.buffer = [byte] + if len(start_bytes) > 1: + self.state = GenericParserState.LOOKING_FOR_START2 + else: + self.state = GenericParserState.GETTING_MSG_ID + + elif self.state == GenericParserState.LOOKING_FOR_START2: + if byte == start_bytes[1]: + self.buffer.append(byte) + self.state = GenericParserState.GETTING_MSG_ID + elif byte == start_bytes[0]: + self.buffer = [byte] + # Stay in LOOKING_FOR_START2 + else: + self.state = GenericParserState.LOOKING_FOR_START1 + + elif self.state == GenericParserState.GETTING_MSG_ID: + self.buffer.append(byte) + self.msg_id = byte + if self.config.has_length: + self.state = GenericParserState.GETTING_LENGTH + elif self.get_msg_length: + msg_len = self.get_msg_length(byte) + if msg_len is not None: + self.packet_size = overhead + msg_len + self.state = GenericParserState.GETTING_PAYLOAD + else: + self.state = self._get_initial_state() + else: + self.state = self._get_initial_state() + + elif self.state == GenericParserState.GETTING_LENGTH: + self.buffer.append(byte) + if self.config.length_bytes == 1: + self.msg_length = byte + self.packet_size = overhead + self.msg_length + self.state = GenericParserState.GETTING_PAYLOAD + else: + # 2-byte length + if len(self.buffer) == len(start_bytes) + 2: + self.length_lo = byte + else: + self.msg_length = self.length_lo | (byte << 8) + self.packet_size = overhead + self.msg_length + self.state = GenericParserState.GETTING_PAYLOAD + + elif self.state == GenericParserState.GETTING_PAYLOAD: + self.buffer.append(byte) + if len(self.buffer) >= self.packet_size: + if self.config.has_crc: + result = validate_payload_with_crc( + self.buffer, self.config.header_size, + self.config.length_bytes, len(start_bytes)) + else: + result = validate_payload_minimal(self.buffer, self.config.header_size) + self.state = self._get_initial_state() + + return result + + def encode(self, msg_id: int, msg: bytes) -> bytes: + """ + Encode a message using this format + + Args: + msg_id: Message ID + msg: Message data bytes + + Returns: + Encoded frame as bytes + """ + output = list(self.config.start_bytes) + + if self.config.has_crc: + encode_payload_with_crc(output, msg_id, msg, + self.config.length_bytes, len(self.config.start_bytes)) + else: + encode_payload_minimal(output, msg_id, msg) + + return bytes(output) + + def encode_msg(self, msg) -> bytes: + """Encode a message object (must have msg_id and pack() method)""" + return self.encode(msg.msg_id, msg.pack()) + + @staticmethod + def validate_packet(config: FrameParserConfig, buffer: Union[bytes, List[int]]) -> FrameMsgInfo: + """ + Validate a complete packet in a buffer + + Args: + config: Frame format configuration + buffer: Buffer containing the complete packet + + Returns: + FrameMsgInfo with valid=True if packet is valid + """ + overhead = config.header_size + config.footer_size + + if len(buffer) < overhead: + return FrameMsgInfo() + + # Check start bytes + for i, start_byte in enumerate(config.start_bytes): + if buffer[i] != start_byte: + return FrameMsgInfo() + + # Validate payload + if config.has_crc: + return validate_payload_with_crc(buffer, config.header_size, + config.length_bytes, len(config.start_bytes)) + else: + return validate_payload_minimal(buffer, config.header_size) + + +def create_frame_parser_class(config: FrameParserConfig): + """ + Create a frame parser class for a specific configuration. + This factory function provides pre-configured parser classes. + """ + class ConfiguredFrameParser(GenericFrameParser): + # Class attributes from config + CONFIG = config + START_BYTES = config.start_bytes + HEADER_SIZE = config.header_size + FOOTER_SIZE = config.footer_size + OVERHEAD = config.header_size + config.footer_size + HAS_LENGTH = config.has_length + LENGTH_BYTES = config.length_bytes + HAS_CRC = config.has_crc + + def __init__(self, get_msg_length: Callable[[int], int] = None): + super().__init__(config, get_msg_length) + + @staticmethod + def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: + return GenericFrameParser.validate_packet(config, buffer) + + ConfiguredFrameParser.__name__ = config.name + ConfiguredFrameParser.__qualname__ = config.name + return ConfiguredFrameParser diff --git a/src/struct_frame/boilerplate/py/frame_format_config.py b/src/struct_frame/boilerplate/py/frame_format_config.py index c375e105..27328a5d 100644 --- a/src/struct_frame/boilerplate/py/frame_format_config.py +++ b/src/struct_frame/boilerplate/py/frame_format_config.py @@ -1,143 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# FrameFormatConfig Frame Format +# FrameFormatConfig Frame Format Configuration # ============================================================================= -class FrameFormatConfigParserState(Enum): - LOOKING_FOR_START1 = 0 - LOOKING_FOR_START2 = 1 - GETTING_MSG_ID = 2 - GETTING_PAYLOAD = 3 - - -class FrameFormatConfig: - """ - FrameFormatConfig - Frame format parser and encoder - - Format: [START_BYTE1=0x90] [START_BYTE2=0x71] [MSG_ID] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE1 = 0x90 - START_BYTE2 = 0x71 - HEADER_SIZE = 2 - FOOTER_SIZE = 1 - OVERHEAD = 3 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the FrameFormatConfig parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = FrameFormatConfigParserState.LOOKING_FOR_START1 - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == FrameFormatConfigParserState.LOOKING_FOR_START1: - if byte == self.START_BYTE1: - self.buffer = [byte] - self.state = FrameFormatConfigParserState.LOOKING_FOR_START2 - - elif self.state == FrameFormatConfigParserState.LOOKING_FOR_START2: - if byte == self.START_BYTE2: - self.buffer.append(byte) - self.state = FrameFormatConfigParserState.GETTING_MSG_ID - elif byte == self.START_BYTE1: - self.buffer = [byte] - self.state = FrameFormatConfigParserState.LOOKING_FOR_START2 - else: - self.state = FrameFormatConfigParserState.LOOKING_FOR_START1 - - elif self.state == FrameFormatConfigParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - if self.get_msg_length: - msg_length = self.get_msg_length(byte) - if msg_length is not None: - self.packet_size = self.OVERHEAD + msg_length - self.state = FrameFormatConfigParserState.GETTING_PAYLOAD - else: - self.state = FrameFormatConfigParserState.LOOKING_FOR_START1 - else: - self.state = FrameFormatConfigParserState.LOOKING_FOR_START1 - - elif self.state == FrameFormatConfigParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 0, 2) - self.state = FrameFormatConfigParserState.LOOKING_FOR_START1 - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with FrameFormatConfig format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE1) - output.append(self.START_BYTE2) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 0, 2) - return bytes(output) +# Configuration for FrameFormatConfig frame format +FrameFormatConfigConfig = FrameParserConfig( + name='FrameFormatConfig', + start_bytes=(0x90, 0x71), + header_size=2, + footer_size=1, + has_length=False, + length_bytes=0, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +FrameFormatConfig - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete FrameFormatConfig packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < FrameFormatConfig.OVERHEAD: - return FrameMsgInfo() +Format: [START_BYTE1=0x90] [START_BYTE2=0x71] [MSG_ID] [MSG...] [CRC1] [CRC2] - if buffer[0] != FrameFormatConfig.START_BYTE1: - return FrameMsgInfo() - if buffer[1] != FrameFormatConfig.START_BYTE2: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +FrameFormatConfig = create_frame_parser_class(FrameFormatConfigConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, FrameFormatConfig.HEADER_SIZE, 0, 2) +# Parser state alias for backward compatibility +FrameFormatConfigParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/mavlink_v1_frame.py b/src/struct_frame/boilerplate/py/mavlink_v1_frame.py index b351009c..ae8abc2f 100644 --- a/src/struct_frame/boilerplate/py/mavlink_v1_frame.py +++ b/src/struct_frame/boilerplate/py/mavlink_v1_frame.py @@ -1,129 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# MavlinkV1Frame Frame Format +# MavlinkV1Frame Frame Format Configuration # ============================================================================= -class MavlinkV1FrameParserState(Enum): - LOOKING_FOR_START = 0 - GETTING_MSG_ID = 1 - GETTING_LENGTH = 2 - GETTING_PAYLOAD = 3 - - -class MavlinkV1Frame: - """ - MavlinkV1Frame - Frame format parser and encoder - - Format: [STX=0xFE] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE = 0xFE - HEADER_SIZE = 6 - FOOTER_SIZE = 2 - OVERHEAD = 8 - LENGTH_BYTES = 1 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the MavlinkV1Frame parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = MavlinkV1FrameParserState.LOOKING_FOR_START - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == MavlinkV1FrameParserState.LOOKING_FOR_START: - if byte == self.START_BYTE: - self.buffer = [byte] - self.state = MavlinkV1FrameParserState.GETTING_MSG_ID - - elif self.state == MavlinkV1FrameParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = MavlinkV1FrameParserState.GETTING_LENGTH - - elif self.state == MavlinkV1FrameParserState.GETTING_LENGTH: - self.buffer.append(byte) - self.msg_length = byte - self.packet_size = self.OVERHEAD + self.msg_length - self.state = MavlinkV1FrameParserState.GETTING_PAYLOAD - - elif self.state == MavlinkV1FrameParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 1, 1) - self.state = MavlinkV1FrameParserState.LOOKING_FOR_START - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with MavlinkV1Frame format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1) - return bytes(output) +# Configuration for MavlinkV1Frame frame format +MavlinkV1FrameConfig = FrameParserConfig( + name='MavlinkV1Frame', + start_bytes=(0xFE,), + header_size=6, + footer_size=2, + has_length=True, + length_bytes=1, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +MavlinkV1Frame - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete MavlinkV1Frame packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < MavlinkV1Frame.OVERHEAD: - return FrameMsgInfo() +Format: [STX=0xFE] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - if buffer[0] != MavlinkV1Frame.START_BYTE: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +MavlinkV1Frame = create_frame_parser_class(MavlinkV1FrameConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, MavlinkV1Frame.HEADER_SIZE, 1, 1) +# Parser state alias for backward compatibility +MavlinkV1FrameParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/mavlink_v2_frame.py b/src/struct_frame/boilerplate/py/mavlink_v2_frame.py index a046e81b..88ff273b 100644 --- a/src/struct_frame/boilerplate/py/mavlink_v2_frame.py +++ b/src/struct_frame/boilerplate/py/mavlink_v2_frame.py @@ -1,129 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# MavlinkV2Frame Frame Format +# MavlinkV2Frame Frame Format Configuration # ============================================================================= -class MavlinkV2FrameParserState(Enum): - LOOKING_FOR_START = 0 - GETTING_MSG_ID = 1 - GETTING_LENGTH = 2 - GETTING_PAYLOAD = 3 - - -class MavlinkV2Frame: - """ - MavlinkV2Frame - Frame format parser and encoder - - Format: [STX=0xFD] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE = 0xFD - HEADER_SIZE = 8 - FOOTER_SIZE = 2 - OVERHEAD = 10 - LENGTH_BYTES = 1 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the MavlinkV2Frame parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = MavlinkV2FrameParserState.LOOKING_FOR_START - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == MavlinkV2FrameParserState.LOOKING_FOR_START: - if byte == self.START_BYTE: - self.buffer = [byte] - self.state = MavlinkV2FrameParserState.GETTING_MSG_ID - - elif self.state == MavlinkV2FrameParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = MavlinkV2FrameParserState.GETTING_LENGTH - - elif self.state == MavlinkV2FrameParserState.GETTING_LENGTH: - self.buffer.append(byte) - self.msg_length = byte - self.packet_size = self.OVERHEAD + self.msg_length - self.state = MavlinkV2FrameParserState.GETTING_PAYLOAD - - elif self.state == MavlinkV2FrameParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 1, 1) - self.state = MavlinkV2FrameParserState.LOOKING_FOR_START - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with MavlinkV2Frame format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1) - return bytes(output) +# Configuration for MavlinkV2Frame frame format +MavlinkV2FrameConfig = FrameParserConfig( + name='MavlinkV2Frame', + start_bytes=(0xFD,), + header_size=8, + footer_size=2, + has_length=True, + length_bytes=1, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +MavlinkV2Frame - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete MavlinkV2Frame packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < MavlinkV2Frame.OVERHEAD: - return FrameMsgInfo() +Format: [STX=0xFD] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - if buffer[0] != MavlinkV2Frame.START_BYTE: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +MavlinkV2Frame = create_frame_parser_class(MavlinkV2FrameConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, MavlinkV2Frame.HEADER_SIZE, 1, 1) +# Parser state alias for backward compatibility +MavlinkV2FrameParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/tiny_default.py b/src/struct_frame/boilerplate/py/tiny_default.py index c085c255..9c491053 100644 --- a/src/struct_frame/boilerplate/py/tiny_default.py +++ b/src/struct_frame/boilerplate/py/tiny_default.py @@ -1,129 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# TinyDefault Frame Format +# TinyDefault Frame Format Configuration # ============================================================================= -class TinyDefaultParserState(Enum): - LOOKING_FOR_START = 0 - GETTING_MSG_ID = 1 - GETTING_LENGTH = 2 - GETTING_PAYLOAD = 3 - - -class TinyDefault: - """ - TinyDefault - Frame format parser and encoder - - Format: [START_BYTE=0x71] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE = 0x71 - HEADER_SIZE = 3 - FOOTER_SIZE = 2 - OVERHEAD = 5 - LENGTH_BYTES = 1 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the TinyDefault parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = TinyDefaultParserState.LOOKING_FOR_START - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == TinyDefaultParserState.LOOKING_FOR_START: - if byte == self.START_BYTE: - self.buffer = [byte] - self.state = TinyDefaultParserState.GETTING_MSG_ID - - elif self.state == TinyDefaultParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = TinyDefaultParserState.GETTING_LENGTH - - elif self.state == TinyDefaultParserState.GETTING_LENGTH: - self.buffer.append(byte) - self.msg_length = byte - self.packet_size = self.OVERHEAD + self.msg_length - self.state = TinyDefaultParserState.GETTING_PAYLOAD - - elif self.state == TinyDefaultParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 1, 1) - self.state = TinyDefaultParserState.LOOKING_FOR_START - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with TinyDefault format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1) - return bytes(output) +# Configuration for TinyDefault frame format +TinyDefaultConfig = FrameParserConfig( + name='TinyDefault', + start_bytes=(0x71,), + header_size=3, + footer_size=2, + has_length=True, + length_bytes=1, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +TinyDefault - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete TinyDefault packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < TinyDefault.OVERHEAD: - return FrameMsgInfo() +Format: [START_BYTE=0x71] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - if buffer[0] != TinyDefault.START_BYTE: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +TinyDefault = create_frame_parser_class(TinyDefaultConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinyDefault.HEADER_SIZE, 1, 1) +# Parser state alias for backward compatibility +TinyDefaultParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/tiny_extended.py b/src/struct_frame/boilerplate/py/tiny_extended.py index 9f72a0cb..de14acd4 100644 --- a/src/struct_frame/boilerplate/py/tiny_extended.py +++ b/src/struct_frame/boilerplate/py/tiny_extended.py @@ -1,133 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# TinyExtended Frame Format +# TinyExtended Frame Format Configuration # ============================================================================= -class TinyExtendedParserState(Enum): - LOOKING_FOR_START = 0 - GETTING_MSG_ID = 1 - GETTING_LENGTH = 2 - GETTING_PAYLOAD = 3 - - -class TinyExtended: - """ - TinyExtended - Frame format parser and encoder - - Format: [START_BYTE=0x74] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE = 0x74 - HEADER_SIZE = 5 - FOOTER_SIZE = 2 - OVERHEAD = 7 - LENGTH_BYTES = 2 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the TinyExtended parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = TinyExtendedParserState.LOOKING_FOR_START - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - self.length_lo = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == TinyExtendedParserState.LOOKING_FOR_START: - if byte == self.START_BYTE: - self.buffer = [byte] - self.state = TinyExtendedParserState.GETTING_MSG_ID - - elif self.state == TinyExtendedParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = TinyExtendedParserState.GETTING_LENGTH - - elif self.state == TinyExtendedParserState.GETTING_LENGTH: - self.buffer.append(byte) - if len(self.buffer) == 3: - self.length_lo = byte - else: - self.msg_length = self.length_lo | (byte << 8) - self.packet_size = self.OVERHEAD + self.msg_length - self.state = TinyExtendedParserState.GETTING_PAYLOAD - - elif self.state == TinyExtendedParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 2, 1) - self.state = TinyExtendedParserState.LOOKING_FOR_START - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with TinyExtended format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 2, 1) - return bytes(output) +# Configuration for TinyExtended frame format +TinyExtendedConfig = FrameParserConfig( + name='TinyExtended', + start_bytes=(0x74,), + header_size=5, + footer_size=2, + has_length=True, + length_bytes=2, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +TinyExtended - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete TinyExtended packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < TinyExtended.OVERHEAD: - return FrameMsgInfo() +Format: [START_BYTE=0x74] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] - if buffer[0] != TinyExtended.START_BYTE: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +TinyExtended = create_frame_parser_class(TinyExtendedConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinyExtended.HEADER_SIZE, 2, 1) +# Parser state alias for backward compatibility +TinyExtendedParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/tiny_extended_length.py b/src/struct_frame/boilerplate/py/tiny_extended_length.py index 4b57fa05..5b231512 100644 --- a/src/struct_frame/boilerplate/py/tiny_extended_length.py +++ b/src/struct_frame/boilerplate/py/tiny_extended_length.py @@ -1,133 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# TinyExtendedLength Frame Format +# TinyExtendedLength Frame Format Configuration # ============================================================================= -class TinyExtendedLengthParserState(Enum): - LOOKING_FOR_START = 0 - GETTING_MSG_ID = 1 - GETTING_LENGTH = 2 - GETTING_PAYLOAD = 3 - - -class TinyExtendedLength: - """ - TinyExtendedLength - Frame format parser and encoder - - Format: [START_BYTE=0x73] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE = 0x73 - HEADER_SIZE = 4 - FOOTER_SIZE = 2 - OVERHEAD = 6 - LENGTH_BYTES = 2 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the TinyExtendedLength parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = TinyExtendedLengthParserState.LOOKING_FOR_START - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - self.length_lo = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == TinyExtendedLengthParserState.LOOKING_FOR_START: - if byte == self.START_BYTE: - self.buffer = [byte] - self.state = TinyExtendedLengthParserState.GETTING_MSG_ID - - elif self.state == TinyExtendedLengthParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = TinyExtendedLengthParserState.GETTING_LENGTH - - elif self.state == TinyExtendedLengthParserState.GETTING_LENGTH: - self.buffer.append(byte) - if len(self.buffer) == 3: - self.length_lo = byte - else: - self.msg_length = self.length_lo | (byte << 8) - self.packet_size = self.OVERHEAD + self.msg_length - self.state = TinyExtendedLengthParserState.GETTING_PAYLOAD - - elif self.state == TinyExtendedLengthParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 2, 1) - self.state = TinyExtendedLengthParserState.LOOKING_FOR_START - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with TinyExtendedLength format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 2, 1) - return bytes(output) +# Configuration for TinyExtendedLength frame format +TinyExtendedLengthConfig = FrameParserConfig( + name='TinyExtendedLength', + start_bytes=(0x73,), + header_size=4, + footer_size=2, + has_length=True, + length_bytes=2, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +TinyExtendedLength - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete TinyExtendedLength packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < TinyExtendedLength.OVERHEAD: - return FrameMsgInfo() +Format: [START_BYTE=0x73] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] - if buffer[0] != TinyExtendedLength.START_BYTE: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +TinyExtendedLength = create_frame_parser_class(TinyExtendedLengthConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinyExtendedLength.HEADER_SIZE, 2, 1) +# Parser state alias for backward compatibility +TinyExtendedLengthParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/tiny_extended_msg_ids.py b/src/struct_frame/boilerplate/py/tiny_extended_msg_ids.py index bed30ef2..f0d4cf52 100644 --- a/src/struct_frame/boilerplate/py/tiny_extended_msg_ids.py +++ b/src/struct_frame/boilerplate/py/tiny_extended_msg_ids.py @@ -1,129 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# TinyExtendedMsgIds Frame Format +# TinyExtendedMsgIds Frame Format Configuration # ============================================================================= -class TinyExtendedMsgIdsParserState(Enum): - LOOKING_FOR_START = 0 - GETTING_MSG_ID = 1 - GETTING_LENGTH = 2 - GETTING_PAYLOAD = 3 - - -class TinyExtendedMsgIds: - """ - TinyExtendedMsgIds - Frame format parser and encoder - - Format: [START_BYTE=0x72] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE = 0x72 - HEADER_SIZE = 4 - FOOTER_SIZE = 2 - OVERHEAD = 6 - LENGTH_BYTES = 1 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the TinyExtendedMsgIds parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = TinyExtendedMsgIdsParserState.LOOKING_FOR_START - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == TinyExtendedMsgIdsParserState.LOOKING_FOR_START: - if byte == self.START_BYTE: - self.buffer = [byte] - self.state = TinyExtendedMsgIdsParserState.GETTING_MSG_ID - - elif self.state == TinyExtendedMsgIdsParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = TinyExtendedMsgIdsParserState.GETTING_LENGTH - - elif self.state == TinyExtendedMsgIdsParserState.GETTING_LENGTH: - self.buffer.append(byte) - self.msg_length = byte - self.packet_size = self.OVERHEAD + self.msg_length - self.state = TinyExtendedMsgIdsParserState.GETTING_PAYLOAD - - elif self.state == TinyExtendedMsgIdsParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 1, 1) - self.state = TinyExtendedMsgIdsParserState.LOOKING_FOR_START - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with TinyExtendedMsgIds format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1) - return bytes(output) +# Configuration for TinyExtendedMsgIds frame format +TinyExtendedMsgIdsConfig = FrameParserConfig( + name='TinyExtendedMsgIds', + start_bytes=(0x72,), + header_size=4, + footer_size=2, + has_length=True, + length_bytes=1, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +TinyExtendedMsgIds - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete TinyExtendedMsgIds packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < TinyExtendedMsgIds.OVERHEAD: - return FrameMsgInfo() +Format: [START_BYTE=0x72] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - if buffer[0] != TinyExtendedMsgIds.START_BYTE: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +TinyExtendedMsgIds = create_frame_parser_class(TinyExtendedMsgIdsConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinyExtendedMsgIds.HEADER_SIZE, 1, 1) +# Parser state alias for backward compatibility +TinyExtendedMsgIdsParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/tiny_extended_multi_system_stream.py b/src/struct_frame/boilerplate/py/tiny_extended_multi_system_stream.py index 1f8b6adb..06ce0dd9 100644 --- a/src/struct_frame/boilerplate/py/tiny_extended_multi_system_stream.py +++ b/src/struct_frame/boilerplate/py/tiny_extended_multi_system_stream.py @@ -1,133 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# TinyExtendedMultiSystemStream Frame Format +# TinyExtendedMultiSystemStream Frame Format Configuration # ============================================================================= -class TinyExtendedMultiSystemStreamParserState(Enum): - LOOKING_FOR_START = 0 - GETTING_MSG_ID = 1 - GETTING_LENGTH = 2 - GETTING_PAYLOAD = 3 - - -class TinyExtendedMultiSystemStream: - """ - TinyExtendedMultiSystemStream - Frame format parser and encoder - - Format: [START_BYTE=0x78] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE = 0x78 - HEADER_SIZE = 8 - FOOTER_SIZE = 2 - OVERHEAD = 10 - LENGTH_BYTES = 2 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the TinyExtendedMultiSystemStream parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - self.length_lo = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START: - if byte == self.START_BYTE: - self.buffer = [byte] - self.state = TinyExtendedMultiSystemStreamParserState.GETTING_MSG_ID - - elif self.state == TinyExtendedMultiSystemStreamParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = TinyExtendedMultiSystemStreamParserState.GETTING_LENGTH - - elif self.state == TinyExtendedMultiSystemStreamParserState.GETTING_LENGTH: - self.buffer.append(byte) - if len(self.buffer) == 3: - self.length_lo = byte - else: - self.msg_length = self.length_lo | (byte << 8) - self.packet_size = self.OVERHEAD + self.msg_length - self.state = TinyExtendedMultiSystemStreamParserState.GETTING_PAYLOAD - - elif self.state == TinyExtendedMultiSystemStreamParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 2, 1) - self.state = TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with TinyExtendedMultiSystemStream format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 2, 1) - return bytes(output) +# Configuration for TinyExtendedMultiSystemStream frame format +TinyExtendedMultiSystemStreamConfig = FrameParserConfig( + name='TinyExtendedMultiSystemStream', + start_bytes=(0x78,), + header_size=8, + footer_size=2, + has_length=True, + length_bytes=2, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +TinyExtendedMultiSystemStream - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete TinyExtendedMultiSystemStream packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < TinyExtendedMultiSystemStream.OVERHEAD: - return FrameMsgInfo() +Format: [START_BYTE=0x78] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] - if buffer[0] != TinyExtendedMultiSystemStream.START_BYTE: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +TinyExtendedMultiSystemStream = create_frame_parser_class(TinyExtendedMultiSystemStreamConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinyExtendedMultiSystemStream.HEADER_SIZE, 2, 1) +# Parser state alias for backward compatibility +TinyExtendedMultiSystemStreamParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/tiny_minimal.py b/src/struct_frame/boilerplate/py/tiny_minimal.py index eeccb9c7..d3f6ca81 100644 --- a/src/struct_frame/boilerplate/py/tiny_minimal.py +++ b/src/struct_frame/boilerplate/py/tiny_minimal.py @@ -1,128 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# TinyMinimal Frame Format +# TinyMinimal Frame Format Configuration # ============================================================================= -class TinyMinimalParserState(Enum): - LOOKING_FOR_START = 0 - GETTING_MSG_ID = 1 - GETTING_PAYLOAD = 2 - - -class TinyMinimal: - """ - TinyMinimal - Frame format parser and encoder - - Format: [START_BYTE=0x70] [MSG_ID] [MSG...] - """ - - START_BYTE = 0x70 - HEADER_SIZE = 2 - FOOTER_SIZE = 0 - OVERHEAD = 2 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the TinyMinimal parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = TinyMinimalParserState.LOOKING_FOR_START - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == TinyMinimalParserState.LOOKING_FOR_START: - if byte == self.START_BYTE: - self.buffer = [byte] - self.state = TinyMinimalParserState.GETTING_MSG_ID - - elif self.state == TinyMinimalParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - if self.get_msg_length: - msg_length = self.get_msg_length(byte) - if msg_length is not None: - self.packet_size = self.OVERHEAD + msg_length - self.state = TinyMinimalParserState.GETTING_PAYLOAD - else: - self.state = TinyMinimalParserState.LOOKING_FOR_START - else: - self.state = TinyMinimalParserState.LOOKING_FOR_START - - elif self.state == TinyMinimalParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared minimal payload validation - result = validate_payload_minimal(self.buffer, self.HEADER_SIZE) - self.state = TinyMinimalParserState.LOOKING_FOR_START - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with TinyMinimal format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE) - # Use shared minimal payload encoding - encode_payload_minimal(output, msg_id, msg) - return bytes(output) +# Configuration for TinyMinimal frame format +TinyMinimalConfig = FrameParserConfig( + name='TinyMinimal', + start_bytes=(0x70,), + header_size=2, + footer_size=0, + has_length=False, + length_bytes=0, + has_crc=False, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +TinyMinimal - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete TinyMinimal packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < TinyMinimal.OVERHEAD: - return FrameMsgInfo() +Format: [START_BYTE=0x70] [MSG_ID] [MSG...] - if buffer[0] != TinyMinimal.START_BYTE: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +TinyMinimal = create_frame_parser_class(TinyMinimalConfig) - # Use shared minimal payload validation - return validate_payload_minimal(buffer, TinyMinimal.HEADER_SIZE) +# Parser state alias for backward compatibility +TinyMinimalParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/tiny_multi_system_stream.py b/src/struct_frame/boilerplate/py/tiny_multi_system_stream.py index 10f43174..2cc94208 100644 --- a/src/struct_frame/boilerplate/py/tiny_multi_system_stream.py +++ b/src/struct_frame/boilerplate/py/tiny_multi_system_stream.py @@ -1,129 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# TinyMultiSystemStream Frame Format +# TinyMultiSystemStream Frame Format Configuration # ============================================================================= -class TinyMultiSystemStreamParserState(Enum): - LOOKING_FOR_START = 0 - GETTING_MSG_ID = 1 - GETTING_LENGTH = 2 - GETTING_PAYLOAD = 3 - - -class TinyMultiSystemStream: - """ - TinyMultiSystemStream - Frame format parser and encoder - - Format: [START_BYTE=0x77] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE = 0x77 - HEADER_SIZE = 6 - FOOTER_SIZE = 2 - OVERHEAD = 8 - LENGTH_BYTES = 1 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the TinyMultiSystemStream parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = TinyMultiSystemStreamParserState.LOOKING_FOR_START - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == TinyMultiSystemStreamParserState.LOOKING_FOR_START: - if byte == self.START_BYTE: - self.buffer = [byte] - self.state = TinyMultiSystemStreamParserState.GETTING_MSG_ID - - elif self.state == TinyMultiSystemStreamParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = TinyMultiSystemStreamParserState.GETTING_LENGTH - - elif self.state == TinyMultiSystemStreamParserState.GETTING_LENGTH: - self.buffer.append(byte) - self.msg_length = byte - self.packet_size = self.OVERHEAD + self.msg_length - self.state = TinyMultiSystemStreamParserState.GETTING_PAYLOAD - - elif self.state == TinyMultiSystemStreamParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 1, 1) - self.state = TinyMultiSystemStreamParserState.LOOKING_FOR_START - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with TinyMultiSystemStream format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1) - return bytes(output) +# Configuration for TinyMultiSystemStream frame format +TinyMultiSystemStreamConfig = FrameParserConfig( + name='TinyMultiSystemStream', + start_bytes=(0x77,), + header_size=6, + footer_size=2, + has_length=True, + length_bytes=1, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +TinyMultiSystemStream - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete TinyMultiSystemStream packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < TinyMultiSystemStream.OVERHEAD: - return FrameMsgInfo() +Format: [START_BYTE=0x77] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - if buffer[0] != TinyMultiSystemStream.START_BYTE: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +TinyMultiSystemStream = create_frame_parser_class(TinyMultiSystemStreamConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinyMultiSystemStream.HEADER_SIZE, 1, 1) +# Parser state alias for backward compatibility +TinyMultiSystemStreamParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/tiny_seq.py b/src/struct_frame/boilerplate/py/tiny_seq.py index 92b57f2f..c4800520 100644 --- a/src/struct_frame/boilerplate/py/tiny_seq.py +++ b/src/struct_frame/boilerplate/py/tiny_seq.py @@ -1,129 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# TinySeq Frame Format +# TinySeq Frame Format Configuration # ============================================================================= -class TinySeqParserState(Enum): - LOOKING_FOR_START = 0 - GETTING_MSG_ID = 1 - GETTING_LENGTH = 2 - GETTING_PAYLOAD = 3 - - -class TinySeq: - """ - TinySeq - Frame format parser and encoder - - Format: [START_BYTE=0x76] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE = 0x76 - HEADER_SIZE = 4 - FOOTER_SIZE = 2 - OVERHEAD = 6 - LENGTH_BYTES = 1 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the TinySeq parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = TinySeqParserState.LOOKING_FOR_START - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == TinySeqParserState.LOOKING_FOR_START: - if byte == self.START_BYTE: - self.buffer = [byte] - self.state = TinySeqParserState.GETTING_MSG_ID - - elif self.state == TinySeqParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = TinySeqParserState.GETTING_LENGTH - - elif self.state == TinySeqParserState.GETTING_LENGTH: - self.buffer.append(byte) - self.msg_length = byte - self.packet_size = self.OVERHEAD + self.msg_length - self.state = TinySeqParserState.GETTING_PAYLOAD - - elif self.state == TinySeqParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 1, 1) - self.state = TinySeqParserState.LOOKING_FOR_START - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with TinySeq format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1) - return bytes(output) +# Configuration for TinySeq frame format +TinySeqConfig = FrameParserConfig( + name='TinySeq', + start_bytes=(0x76,), + header_size=4, + footer_size=2, + has_length=True, + length_bytes=1, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +TinySeq - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete TinySeq packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < TinySeq.OVERHEAD: - return FrameMsgInfo() +Format: [START_BYTE=0x76] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - if buffer[0] != TinySeq.START_BYTE: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +TinySeq = create_frame_parser_class(TinySeqConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinySeq.HEADER_SIZE, 1, 1) +# Parser state alias for backward compatibility +TinySeqParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/tiny_sys_comp.py b/src/struct_frame/boilerplate/py/tiny_sys_comp.py index c4a40e32..2735a2f8 100644 --- a/src/struct_frame/boilerplate/py/tiny_sys_comp.py +++ b/src/struct_frame/boilerplate/py/tiny_sys_comp.py @@ -1,129 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# TinySysComp Frame Format +# TinySysComp Frame Format Configuration # ============================================================================= -class TinySysCompParserState(Enum): - LOOKING_FOR_START = 0 - GETTING_MSG_ID = 1 - GETTING_LENGTH = 2 - GETTING_PAYLOAD = 3 - - -class TinySysComp: - """ - TinySysComp - Frame format parser and encoder - - Format: [START_BYTE=0x75] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE = 0x75 - HEADER_SIZE = 5 - FOOTER_SIZE = 2 - OVERHEAD = 7 - LENGTH_BYTES = 1 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the TinySysComp parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = TinySysCompParserState.LOOKING_FOR_START - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == TinySysCompParserState.LOOKING_FOR_START: - if byte == self.START_BYTE: - self.buffer = [byte] - self.state = TinySysCompParserState.GETTING_MSG_ID - - elif self.state == TinySysCompParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = TinySysCompParserState.GETTING_LENGTH - - elif self.state == TinySysCompParserState.GETTING_LENGTH: - self.buffer.append(byte) - self.msg_length = byte - self.packet_size = self.OVERHEAD + self.msg_length - self.state = TinySysCompParserState.GETTING_PAYLOAD - - elif self.state == TinySysCompParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 1, 1) - self.state = TinySysCompParserState.LOOKING_FOR_START - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with TinySysComp format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1) - return bytes(output) +# Configuration for TinySysComp frame format +TinySysCompConfig = FrameParserConfig( + name='TinySysComp', + start_bytes=(0x75,), + header_size=5, + footer_size=2, + has_length=True, + length_bytes=1, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +TinySysComp - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete TinySysComp packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < TinySysComp.OVERHEAD: - return FrameMsgInfo() +Format: [START_BYTE=0x75] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - if buffer[0] != TinySysComp.START_BYTE: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +TinySysComp = create_frame_parser_class(TinySysCompConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinySysComp.HEADER_SIZE, 1, 1) +# Parser state alias for backward compatibility +TinySysCompParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/py/ubx_frame.py b/src/struct_frame/boilerplate/py/ubx_frame.py index 6938ee7b..ceeb3e48 100644 --- a/src/struct_frame/boilerplate/py/ubx_frame.py +++ b/src/struct_frame/boilerplate/py/ubx_frame.py @@ -1,144 +1,33 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +# Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -from enum import Enum -from typing import Callable, List, Union from .frame_base import ( - FrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, create_frame_parser_class, GenericParserState, ) # ============================================================================= -# UbxFrame Frame Format +# UbxFrame Frame Format Configuration # ============================================================================= -class UbxFrameParserState(Enum): - LOOKING_FOR_START1 = 0 - LOOKING_FOR_START2 = 1 - GETTING_MSG_ID = 2 - GETTING_LENGTH = 3 - GETTING_PAYLOAD = 4 - - -class UbxFrame: - """ - UbxFrame - Frame format parser and encoder - - Format: [SYNC1=0xB5] [SYNC2=0x62] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - """ - - START_BYTE1 = 0xB5 - START_BYTE2 = 0x62 - HEADER_SIZE = 5 - FOOTER_SIZE = 2 - OVERHEAD = 7 - LENGTH_BYTES = 1 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the UbxFrame parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = UbxFrameParserState.LOOKING_FOR_START1 - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == UbxFrameParserState.LOOKING_FOR_START1: - if byte == self.START_BYTE1: - self.buffer = [byte] - self.state = UbxFrameParserState.LOOKING_FOR_START2 - - elif self.state == UbxFrameParserState.LOOKING_FOR_START2: - if byte == self.START_BYTE2: - self.buffer.append(byte) - self.state = UbxFrameParserState.GETTING_MSG_ID - elif byte == self.START_BYTE1: - self.buffer = [byte] - self.state = UbxFrameParserState.LOOKING_FOR_START2 - else: - self.state = UbxFrameParserState.LOOKING_FOR_START1 - - elif self.state == UbxFrameParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = UbxFrameParserState.GETTING_LENGTH - - elif self.state == UbxFrameParserState.GETTING_LENGTH: - self.buffer.append(byte) - self.msg_length = byte - self.packet_size = self.OVERHEAD + self.msg_length - self.state = UbxFrameParserState.GETTING_PAYLOAD - - elif self.state == UbxFrameParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Use shared payload validation with CRC - result = validate_payload_with_crc(self.buffer, self.HEADER_SIZE, 1, 2) - self.state = UbxFrameParserState.LOOKING_FOR_START1 - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with UbxFrame format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE1) - output.append(self.START_BYTE2) - # Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 2) - return bytes(output) +# Configuration for UbxFrame frame format +UbxFrameConfig = FrameParserConfig( + name='UbxFrame', + start_bytes=(0xB5, 0x62), + header_size=5, + footer_size=2, + has_length=True, + length_bytes=1, + has_crc=True, +) - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) +""" +UbxFrame - Frame format parser and encoder - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete UbxFrame packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - if len(buffer) < UbxFrame.OVERHEAD: - return FrameMsgInfo() +Format: [SYNC1=0xB5] [SYNC2=0x62] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] - if buffer[0] != UbxFrame.START_BYTE1: - return FrameMsgInfo() - if buffer[1] != UbxFrame.START_BYTE2: - return FrameMsgInfo() +This class is generated using create_frame_parser_class() for code reuse. +""" +UbxFrame = create_frame_parser_class(UbxFrameConfig) - # Use shared payload validation with CRC - return validate_payload_with_crc(buffer, UbxFrame.HEADER_SIZE, 1, 2) +# Parser state alias for backward compatibility +UbxFrameParserState = GenericParserState diff --git a/src/struct_frame/boilerplate/ts/BasicDefault.ts b/src/struct_frame/boilerplate/ts/BasicDefault.ts index 49ff2901..c43b84a1 100644 --- a/src/struct_frame/boilerplate/ts/BasicDefault.ts +++ b/src/struct_frame/boilerplate/ts/BasicDefault.ts @@ -1,160 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// BasicDefault Frame Format +// BasicDefault Frame Format Configuration // ============================================================================= -export enum BasicDefaultParserState { - LOOKING_FOR_START1 = 0, - LOOKING_FOR_START2 = 1, - GETTING_MSG_ID = 2, - GETTING_LENGTH = 3, - GETTING_PAYLOAD = 4 -} +/** Configuration for BasicDefault frame format */ +export const BasicDefaultConfig: FrameParserConfig = { + name: 'BasicDefault', + startBytes: [0x90, 0x71], + headerSize: 4, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, +}; /** * BasicDefault - Frame format parser and encoder * * Format: [START_BYTE1=0x90] [START_BYTE2=0x71] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class BasicDefault { - static readonly START_BYTE1 = 0x90; - static readonly START_BYTE2 = 0x71; - static readonly HEADER_SIZE = 4; - static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 6; - static readonly LENGTH_BYTES = 1; +export const BasicDefault = createFrameParserClass(BasicDefaultConfig); - private state: BasicDefaultParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private msg_length: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new BasicDefault parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = BasicDefaultParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = BasicDefaultParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case BasicDefaultParserState.LOOKING_FOR_START1: - if (byte === BasicDefault.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicDefaultParserState.LOOKING_FOR_START2; - } - break; - - case BasicDefaultParserState.LOOKING_FOR_START2: - if (byte === BasicDefault.START_BYTE2) { - this.buffer.push(byte); - this.state = BasicDefaultParserState.GETTING_MSG_ID; - } else if (byte === BasicDefault.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicDefaultParserState.LOOKING_FOR_START2; - } else { - this.state = BasicDefaultParserState.LOOKING_FOR_START1; - } - break; - - case BasicDefaultParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = BasicDefaultParserState.GETTING_LENGTH; - break; - - case BasicDefaultParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = BasicDefault.OVERHEAD + this.msg_length; - this.state = BasicDefaultParserState.GETTING_PAYLOAD; - break; - - case BasicDefaultParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, BasicDefault.HEADER_SIZE, 1, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = BasicDefaultParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - /** - * Encode a message with BasicDefault format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(BasicDefault.START_BYTE1); - output.push(BasicDefault.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 2); - return new Uint8Array(output); - } - - /** - * Validate a complete BasicDefault packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < BasicDefault.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== BasicDefault.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== BasicDefault.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicDefault.HEADER_SIZE, 1, 2); - } -} +/** Parser state type alias for backward compatibility */ +export type BasicDefaultParserState = GenericParserState; +export { GenericParserState as BasicDefaultParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/BasicExtended.ts b/src/struct_frame/boilerplate/ts/BasicExtended.ts index ff76fdbd..3c58f8d8 100644 --- a/src/struct_frame/boilerplate/ts/BasicExtended.ts +++ b/src/struct_frame/boilerplate/ts/BasicExtended.ts @@ -1,166 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// BasicExtended Frame Format +// BasicExtended Frame Format Configuration // ============================================================================= -export enum BasicExtendedParserState { - LOOKING_FOR_START1 = 0, - LOOKING_FOR_START2 = 1, - GETTING_MSG_ID = 2, - GETTING_LENGTH = 3, - GETTING_PAYLOAD = 4 -} +/** Configuration for BasicExtended frame format */ +export const BasicExtendedConfig: FrameParserConfig = { + name: 'BasicExtended', + startBytes: [0x90, 0x74], + headerSize: 6, + footerSize: 2, + hasLength: true, + lengthBytes: 2, + hasCrc: true, +}; /** * BasicExtended - Frame format parser and encoder * * Format: [START_BYTE1=0x90] [START_BYTE2=0x74] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class BasicExtended { - static readonly START_BYTE1 = 0x90; - static readonly START_BYTE2 = 0x74; - static readonly HEADER_SIZE = 6; - static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 8; - static readonly LENGTH_BYTES = 2; +export const BasicExtended = createFrameParserClass(BasicExtendedConfig); - private state: BasicExtendedParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private msg_length: number; - private length_lo: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new BasicExtended parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = BasicExtendedParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - this.length_lo = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = BasicExtendedParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case BasicExtendedParserState.LOOKING_FOR_START1: - if (byte === BasicExtended.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicExtendedParserState.LOOKING_FOR_START2; - } - break; - - case BasicExtendedParserState.LOOKING_FOR_START2: - if (byte === BasicExtended.START_BYTE2) { - this.buffer.push(byte); - this.state = BasicExtendedParserState.GETTING_MSG_ID; - } else if (byte === BasicExtended.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicExtendedParserState.LOOKING_FOR_START2; - } else { - this.state = BasicExtendedParserState.LOOKING_FOR_START1; - } - break; - - case BasicExtendedParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = BasicExtendedParserState.GETTING_LENGTH; - break; - - case BasicExtendedParserState.GETTING_LENGTH: - this.buffer.push(byte); - if (this.buffer.length === 4) { - this.length_lo = byte; - } else { - this.msg_length = this.length_lo | (byte << 8); - this.packet_size = BasicExtended.OVERHEAD + this.msg_length; - this.state = BasicExtendedParserState.GETTING_PAYLOAD; - } - break; - - case BasicExtendedParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, BasicExtended.HEADER_SIZE, 2, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = BasicExtendedParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - /** - * Encode a message with BasicExtended format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(BasicExtended.START_BYTE1); - output.push(BasicExtended.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 2, 2); - return new Uint8Array(output); - } - - /** - * Validate a complete BasicExtended packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < BasicExtended.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== BasicExtended.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== BasicExtended.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicExtended.HEADER_SIZE, 2, 2); - } -} +/** Parser state type alias for backward compatibility */ +export type BasicExtendedParserState = GenericParserState; +export { GenericParserState as BasicExtendedParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/BasicExtendedLength.ts b/src/struct_frame/boilerplate/ts/BasicExtendedLength.ts index 46788e2b..fff6a52f 100644 --- a/src/struct_frame/boilerplate/ts/BasicExtendedLength.ts +++ b/src/struct_frame/boilerplate/ts/BasicExtendedLength.ts @@ -1,166 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// BasicExtendedLength Frame Format +// BasicExtendedLength Frame Format Configuration // ============================================================================= -export enum BasicExtendedLengthParserState { - LOOKING_FOR_START1 = 0, - LOOKING_FOR_START2 = 1, - GETTING_MSG_ID = 2, - GETTING_LENGTH = 3, - GETTING_PAYLOAD = 4 -} +/** Configuration for BasicExtendedLength frame format */ +export const BasicExtendedLengthConfig: FrameParserConfig = { + name: 'BasicExtendedLength', + startBytes: [0x90, 0x73], + headerSize: 5, + footerSize: 2, + hasLength: true, + lengthBytes: 2, + hasCrc: true, +}; /** * BasicExtendedLength - Frame format parser and encoder * * Format: [START_BYTE1=0x90] [START_BYTE2=0x73] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class BasicExtendedLength { - static readonly START_BYTE1 = 0x90; - static readonly START_BYTE2 = 0x73; - static readonly HEADER_SIZE = 5; - static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 7; - static readonly LENGTH_BYTES = 2; +export const BasicExtendedLength = createFrameParserClass(BasicExtendedLengthConfig); - private state: BasicExtendedLengthParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private msg_length: number; - private length_lo: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new BasicExtendedLength parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = BasicExtendedLengthParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - this.length_lo = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = BasicExtendedLengthParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case BasicExtendedLengthParserState.LOOKING_FOR_START1: - if (byte === BasicExtendedLength.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicExtendedLengthParserState.LOOKING_FOR_START2; - } - break; - - case BasicExtendedLengthParserState.LOOKING_FOR_START2: - if (byte === BasicExtendedLength.START_BYTE2) { - this.buffer.push(byte); - this.state = BasicExtendedLengthParserState.GETTING_MSG_ID; - } else if (byte === BasicExtendedLength.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicExtendedLengthParserState.LOOKING_FOR_START2; - } else { - this.state = BasicExtendedLengthParserState.LOOKING_FOR_START1; - } - break; - - case BasicExtendedLengthParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = BasicExtendedLengthParserState.GETTING_LENGTH; - break; - - case BasicExtendedLengthParserState.GETTING_LENGTH: - this.buffer.push(byte); - if (this.buffer.length === 4) { - this.length_lo = byte; - } else { - this.msg_length = this.length_lo | (byte << 8); - this.packet_size = BasicExtendedLength.OVERHEAD + this.msg_length; - this.state = BasicExtendedLengthParserState.GETTING_PAYLOAD; - } - break; - - case BasicExtendedLengthParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, BasicExtendedLength.HEADER_SIZE, 2, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = BasicExtendedLengthParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - /** - * Encode a message with BasicExtendedLength format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(BasicExtendedLength.START_BYTE1); - output.push(BasicExtendedLength.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 2, 2); - return new Uint8Array(output); - } - - /** - * Validate a complete BasicExtendedLength packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < BasicExtendedLength.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== BasicExtendedLength.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== BasicExtendedLength.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicExtendedLength.HEADER_SIZE, 2, 2); - } -} +/** Parser state type alias for backward compatibility */ +export type BasicExtendedLengthParserState = GenericParserState; +export { GenericParserState as BasicExtendedLengthParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/BasicExtendedMsgIds.ts b/src/struct_frame/boilerplate/ts/BasicExtendedMsgIds.ts index de274a05..0c7f8994 100644 --- a/src/struct_frame/boilerplate/ts/BasicExtendedMsgIds.ts +++ b/src/struct_frame/boilerplate/ts/BasicExtendedMsgIds.ts @@ -1,160 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// BasicExtendedMsgIds Frame Format +// BasicExtendedMsgIds Frame Format Configuration // ============================================================================= -export enum BasicExtendedMsgIdsParserState { - LOOKING_FOR_START1 = 0, - LOOKING_FOR_START2 = 1, - GETTING_MSG_ID = 2, - GETTING_LENGTH = 3, - GETTING_PAYLOAD = 4 -} +/** Configuration for BasicExtendedMsgIds frame format */ +export const BasicExtendedMsgIdsConfig: FrameParserConfig = { + name: 'BasicExtendedMsgIds', + startBytes: [0x90, 0x72], + headerSize: 5, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, +}; /** * BasicExtendedMsgIds - Frame format parser and encoder * * Format: [START_BYTE1=0x90] [START_BYTE2=0x72] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class BasicExtendedMsgIds { - static readonly START_BYTE1 = 0x90; - static readonly START_BYTE2 = 0x72; - static readonly HEADER_SIZE = 5; - static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 7; - static readonly LENGTH_BYTES = 1; +export const BasicExtendedMsgIds = createFrameParserClass(BasicExtendedMsgIdsConfig); - private state: BasicExtendedMsgIdsParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private msg_length: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new BasicExtendedMsgIds parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case BasicExtendedMsgIdsParserState.LOOKING_FOR_START1: - if (byte === BasicExtendedMsgIds.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START2; - } - break; - - case BasicExtendedMsgIdsParserState.LOOKING_FOR_START2: - if (byte === BasicExtendedMsgIds.START_BYTE2) { - this.buffer.push(byte); - this.state = BasicExtendedMsgIdsParserState.GETTING_MSG_ID; - } else if (byte === BasicExtendedMsgIds.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START2; - } else { - this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1; - } - break; - - case BasicExtendedMsgIdsParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = BasicExtendedMsgIdsParserState.GETTING_LENGTH; - break; - - case BasicExtendedMsgIdsParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = BasicExtendedMsgIds.OVERHEAD + this.msg_length; - this.state = BasicExtendedMsgIdsParserState.GETTING_PAYLOAD; - break; - - case BasicExtendedMsgIdsParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, BasicExtendedMsgIds.HEADER_SIZE, 1, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - /** - * Encode a message with BasicExtendedMsgIds format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(BasicExtendedMsgIds.START_BYTE1); - output.push(BasicExtendedMsgIds.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 2); - return new Uint8Array(output); - } - - /** - * Validate a complete BasicExtendedMsgIds packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < BasicExtendedMsgIds.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== BasicExtendedMsgIds.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== BasicExtendedMsgIds.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicExtendedMsgIds.HEADER_SIZE, 1, 2); - } -} +/** Parser state type alias for backward compatibility */ +export type BasicExtendedMsgIdsParserState = GenericParserState; +export { GenericParserState as BasicExtendedMsgIdsParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/BasicExtendedMultiSystemStream.ts b/src/struct_frame/boilerplate/ts/BasicExtendedMultiSystemStream.ts index de25edef..73df40f8 100644 --- a/src/struct_frame/boilerplate/ts/BasicExtendedMultiSystemStream.ts +++ b/src/struct_frame/boilerplate/ts/BasicExtendedMultiSystemStream.ts @@ -1,166 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// BasicExtendedMultiSystemStream Frame Format +// BasicExtendedMultiSystemStream Frame Format Configuration // ============================================================================= -export enum BasicExtendedMultiSystemStreamParserState { - LOOKING_FOR_START1 = 0, - LOOKING_FOR_START2 = 1, - GETTING_MSG_ID = 2, - GETTING_LENGTH = 3, - GETTING_PAYLOAD = 4 -} +/** Configuration for BasicExtendedMultiSystemStream frame format */ +export const BasicExtendedMultiSystemStreamConfig: FrameParserConfig = { + name: 'BasicExtendedMultiSystemStream', + startBytes: [0x90, 0x78], + headerSize: 9, + footerSize: 2, + hasLength: true, + lengthBytes: 2, + hasCrc: true, +}; /** * BasicExtendedMultiSystemStream - Frame format parser and encoder * * Format: [START_BYTE1=0x90] [START_BYTE2=0x78] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class BasicExtendedMultiSystemStream { - static readonly START_BYTE1 = 0x90; - static readonly START_BYTE2 = 0x78; - static readonly HEADER_SIZE = 9; - static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 11; - static readonly LENGTH_BYTES = 2; +export const BasicExtendedMultiSystemStream = createFrameParserClass(BasicExtendedMultiSystemStreamConfig); - private state: BasicExtendedMultiSystemStreamParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private msg_length: number; - private length_lo: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new BasicExtendedMultiSystemStream parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - this.length_lo = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1: - if (byte === BasicExtendedMultiSystemStream.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START2; - } - break; - - case BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START2: - if (byte === BasicExtendedMultiSystemStream.START_BYTE2) { - this.buffer.push(byte); - this.state = BasicExtendedMultiSystemStreamParserState.GETTING_MSG_ID; - } else if (byte === BasicExtendedMultiSystemStream.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START2; - } else { - this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1; - } - break; - - case BasicExtendedMultiSystemStreamParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = BasicExtendedMultiSystemStreamParserState.GETTING_LENGTH; - break; - - case BasicExtendedMultiSystemStreamParserState.GETTING_LENGTH: - this.buffer.push(byte); - if (this.buffer.length === 4) { - this.length_lo = byte; - } else { - this.msg_length = this.length_lo | (byte << 8); - this.packet_size = BasicExtendedMultiSystemStream.OVERHEAD + this.msg_length; - this.state = BasicExtendedMultiSystemStreamParserState.GETTING_PAYLOAD; - } - break; - - case BasicExtendedMultiSystemStreamParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, BasicExtendedMultiSystemStream.HEADER_SIZE, 2, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - /** - * Encode a message with BasicExtendedMultiSystemStream format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(BasicExtendedMultiSystemStream.START_BYTE1); - output.push(BasicExtendedMultiSystemStream.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 2, 2); - return new Uint8Array(output); - } - - /** - * Validate a complete BasicExtendedMultiSystemStream packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < BasicExtendedMultiSystemStream.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== BasicExtendedMultiSystemStream.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== BasicExtendedMultiSystemStream.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicExtendedMultiSystemStream.HEADER_SIZE, 2, 2); - } -} +/** Parser state type alias for backward compatibility */ +export type BasicExtendedMultiSystemStreamParserState = GenericParserState; +export { GenericParserState as BasicExtendedMultiSystemStreamParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/BasicMinimal.ts b/src/struct_frame/boilerplate/ts/BasicMinimal.ts index 8a8362d2..ecd3e859 100644 --- a/src/struct_frame/boilerplate/ts/BasicMinimal.ts +++ b/src/struct_frame/boilerplate/ts/BasicMinimal.ts @@ -1,156 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// BasicMinimal Frame Format +// BasicMinimal Frame Format Configuration // ============================================================================= -export enum BasicMinimalParserState { - LOOKING_FOR_START1 = 0, - LOOKING_FOR_START2 = 1, - GETTING_MSG_ID = 2, - GETTING_PAYLOAD = 3 -} +/** Configuration for BasicMinimal frame format */ +export const BasicMinimalConfig: FrameParserConfig = { + name: 'BasicMinimal', + startBytes: [0x90, 0x70], + headerSize: 3, + footerSize: 0, + hasLength: false, + lengthBytes: 0, + hasCrc: false, +}; /** * BasicMinimal - Frame format parser and encoder * * Format: [START_BYTE1=0x90] [START_BYTE2=0x70] [MSG_ID] [MSG...] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class BasicMinimal { - static readonly START_BYTE1 = 0x90; - static readonly START_BYTE2 = 0x70; - static readonly HEADER_SIZE = 3; - static readonly FOOTER_SIZE = 0; - static readonly OVERHEAD = 3; +export const BasicMinimal = createFrameParserClass(BasicMinimalConfig); - private state: BasicMinimalParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new BasicMinimal parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = BasicMinimalParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = BasicMinimalParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case BasicMinimalParserState.LOOKING_FOR_START1: - if (byte === BasicMinimal.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicMinimalParserState.LOOKING_FOR_START2; - } - break; - - case BasicMinimalParserState.LOOKING_FOR_START2: - if (byte === BasicMinimal.START_BYTE2) { - this.buffer.push(byte); - this.state = BasicMinimalParserState.GETTING_MSG_ID; - } else if (byte === BasicMinimal.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicMinimalParserState.LOOKING_FOR_START2; - } else { - this.state = BasicMinimalParserState.LOOKING_FOR_START1; - } - break; - - case BasicMinimalParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - if (this.get_msg_length) { - const msg_length = this.get_msg_length(byte); - if (msg_length !== undefined) { - this.packet_size = BasicMinimal.OVERHEAD + msg_length; - this.state = BasicMinimalParserState.GETTING_PAYLOAD; - } else { - this.state = BasicMinimalParserState.LOOKING_FOR_START1; - } - } else { - this.state = BasicMinimalParserState.LOOKING_FOR_START1; - } - break; - - case BasicMinimalParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared minimal payload validation - const validationResult = validate_payload_minimal(this.buffer, BasicMinimal.HEADER_SIZE); - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - this.state = BasicMinimalParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - /** - * Encode a message with BasicMinimal format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(BasicMinimal.START_BYTE1); - output.push(BasicMinimal.START_BYTE2); - // Use shared minimal payload encoding - encode_payload_minimal(output, msg_id, msg); - return new Uint8Array(output); - } - - /** - * Validate a complete BasicMinimal packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < BasicMinimal.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== BasicMinimal.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== BasicMinimal.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared minimal payload validation - return validate_payload_minimal(buffer, BasicMinimal.HEADER_SIZE); - } -} +/** Parser state type alias for backward compatibility */ +export type BasicMinimalParserState = GenericParserState; +export { GenericParserState as BasicMinimalParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/BasicMultiSystemStream.ts b/src/struct_frame/boilerplate/ts/BasicMultiSystemStream.ts index 7464f456..b41e01fe 100644 --- a/src/struct_frame/boilerplate/ts/BasicMultiSystemStream.ts +++ b/src/struct_frame/boilerplate/ts/BasicMultiSystemStream.ts @@ -1,160 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// BasicMultiSystemStream Frame Format +// BasicMultiSystemStream Frame Format Configuration // ============================================================================= -export enum BasicMultiSystemStreamParserState { - LOOKING_FOR_START1 = 0, - LOOKING_FOR_START2 = 1, - GETTING_MSG_ID = 2, - GETTING_LENGTH = 3, - GETTING_PAYLOAD = 4 -} +/** Configuration for BasicMultiSystemStream frame format */ +export const BasicMultiSystemStreamConfig: FrameParserConfig = { + name: 'BasicMultiSystemStream', + startBytes: [0x90, 0x77], + headerSize: 7, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, +}; /** * BasicMultiSystemStream - Frame format parser and encoder * * Format: [START_BYTE1=0x90] [START_BYTE2=0x77] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class BasicMultiSystemStream { - static readonly START_BYTE1 = 0x90; - static readonly START_BYTE2 = 0x77; - static readonly HEADER_SIZE = 7; - static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 9; - static readonly LENGTH_BYTES = 1; +export const BasicMultiSystemStream = createFrameParserClass(BasicMultiSystemStreamConfig); - private state: BasicMultiSystemStreamParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private msg_length: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new BasicMultiSystemStream parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case BasicMultiSystemStreamParserState.LOOKING_FOR_START1: - if (byte === BasicMultiSystemStream.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START2; - } - break; - - case BasicMultiSystemStreamParserState.LOOKING_FOR_START2: - if (byte === BasicMultiSystemStream.START_BYTE2) { - this.buffer.push(byte); - this.state = BasicMultiSystemStreamParserState.GETTING_MSG_ID; - } else if (byte === BasicMultiSystemStream.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START2; - } else { - this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1; - } - break; - - case BasicMultiSystemStreamParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = BasicMultiSystemStreamParserState.GETTING_LENGTH; - break; - - case BasicMultiSystemStreamParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = BasicMultiSystemStream.OVERHEAD + this.msg_length; - this.state = BasicMultiSystemStreamParserState.GETTING_PAYLOAD; - break; - - case BasicMultiSystemStreamParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, BasicMultiSystemStream.HEADER_SIZE, 1, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - /** - * Encode a message with BasicMultiSystemStream format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(BasicMultiSystemStream.START_BYTE1); - output.push(BasicMultiSystemStream.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 2); - return new Uint8Array(output); - } - - /** - * Validate a complete BasicMultiSystemStream packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < BasicMultiSystemStream.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== BasicMultiSystemStream.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== BasicMultiSystemStream.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicMultiSystemStream.HEADER_SIZE, 1, 2); - } -} +/** Parser state type alias for backward compatibility */ +export type BasicMultiSystemStreamParserState = GenericParserState; +export { GenericParserState as BasicMultiSystemStreamParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/BasicSeq.ts b/src/struct_frame/boilerplate/ts/BasicSeq.ts index 551c357d..d7af1043 100644 --- a/src/struct_frame/boilerplate/ts/BasicSeq.ts +++ b/src/struct_frame/boilerplate/ts/BasicSeq.ts @@ -1,160 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// BasicSeq Frame Format +// BasicSeq Frame Format Configuration // ============================================================================= -export enum BasicSeqParserState { - LOOKING_FOR_START1 = 0, - LOOKING_FOR_START2 = 1, - GETTING_MSG_ID = 2, - GETTING_LENGTH = 3, - GETTING_PAYLOAD = 4 -} +/** Configuration for BasicSeq frame format */ +export const BasicSeqConfig: FrameParserConfig = { + name: 'BasicSeq', + startBytes: [0x90, 0x76], + headerSize: 5, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, +}; /** * BasicSeq - Frame format parser and encoder * * Format: [START_BYTE1=0x90] [START_BYTE2=0x76] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class BasicSeq { - static readonly START_BYTE1 = 0x90; - static readonly START_BYTE2 = 0x76; - static readonly HEADER_SIZE = 5; - static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 7; - static readonly LENGTH_BYTES = 1; +export const BasicSeq = createFrameParserClass(BasicSeqConfig); - private state: BasicSeqParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private msg_length: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new BasicSeq parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = BasicSeqParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = BasicSeqParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case BasicSeqParserState.LOOKING_FOR_START1: - if (byte === BasicSeq.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicSeqParserState.LOOKING_FOR_START2; - } - break; - - case BasicSeqParserState.LOOKING_FOR_START2: - if (byte === BasicSeq.START_BYTE2) { - this.buffer.push(byte); - this.state = BasicSeqParserState.GETTING_MSG_ID; - } else if (byte === BasicSeq.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicSeqParserState.LOOKING_FOR_START2; - } else { - this.state = BasicSeqParserState.LOOKING_FOR_START1; - } - break; - - case BasicSeqParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = BasicSeqParserState.GETTING_LENGTH; - break; - - case BasicSeqParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = BasicSeq.OVERHEAD + this.msg_length; - this.state = BasicSeqParserState.GETTING_PAYLOAD; - break; - - case BasicSeqParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, BasicSeq.HEADER_SIZE, 1, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = BasicSeqParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - /** - * Encode a message with BasicSeq format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(BasicSeq.START_BYTE1); - output.push(BasicSeq.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 2); - return new Uint8Array(output); - } - - /** - * Validate a complete BasicSeq packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < BasicSeq.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== BasicSeq.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== BasicSeq.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicSeq.HEADER_SIZE, 1, 2); - } -} +/** Parser state type alias for backward compatibility */ +export type BasicSeqParserState = GenericParserState; +export { GenericParserState as BasicSeqParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/BasicSysComp.ts b/src/struct_frame/boilerplate/ts/BasicSysComp.ts index 7e86fe1c..d1c1f67f 100644 --- a/src/struct_frame/boilerplate/ts/BasicSysComp.ts +++ b/src/struct_frame/boilerplate/ts/BasicSysComp.ts @@ -1,160 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// BasicSysComp Frame Format +// BasicSysComp Frame Format Configuration // ============================================================================= -export enum BasicSysCompParserState { - LOOKING_FOR_START1 = 0, - LOOKING_FOR_START2 = 1, - GETTING_MSG_ID = 2, - GETTING_LENGTH = 3, - GETTING_PAYLOAD = 4 -} +/** Configuration for BasicSysComp frame format */ +export const BasicSysCompConfig: FrameParserConfig = { + name: 'BasicSysComp', + startBytes: [0x90, 0x75], + headerSize: 6, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, +}; /** * BasicSysComp - Frame format parser and encoder * * Format: [START_BYTE1=0x90] [START_BYTE2=0x75] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class BasicSysComp { - static readonly START_BYTE1 = 0x90; - static readonly START_BYTE2 = 0x75; - static readonly HEADER_SIZE = 6; - static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 8; - static readonly LENGTH_BYTES = 1; +export const BasicSysComp = createFrameParserClass(BasicSysCompConfig); - private state: BasicSysCompParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private msg_length: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new BasicSysComp parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = BasicSysCompParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = BasicSysCompParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case BasicSysCompParserState.LOOKING_FOR_START1: - if (byte === BasicSysComp.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicSysCompParserState.LOOKING_FOR_START2; - } - break; - - case BasicSysCompParserState.LOOKING_FOR_START2: - if (byte === BasicSysComp.START_BYTE2) { - this.buffer.push(byte); - this.state = BasicSysCompParserState.GETTING_MSG_ID; - } else if (byte === BasicSysComp.START_BYTE1) { - this.buffer = [byte]; - this.state = BasicSysCompParserState.LOOKING_FOR_START2; - } else { - this.state = BasicSysCompParserState.LOOKING_FOR_START1; - } - break; - - case BasicSysCompParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = BasicSysCompParserState.GETTING_LENGTH; - break; - - case BasicSysCompParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = BasicSysComp.OVERHEAD + this.msg_length; - this.state = BasicSysCompParserState.GETTING_PAYLOAD; - break; - - case BasicSysCompParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, BasicSysComp.HEADER_SIZE, 1, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = BasicSysCompParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - /** - * Encode a message with BasicSysComp format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(BasicSysComp.START_BYTE1); - output.push(BasicSysComp.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 2); - return new Uint8Array(output); - } - - /** - * Validate a complete BasicSysComp packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < BasicSysComp.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== BasicSysComp.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== BasicSysComp.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, BasicSysComp.HEADER_SIZE, 1, 2); - } -} +/** Parser state type alias for backward compatibility */ +export type BasicSysCompParserState = GenericParserState; +export { GenericParserState as BasicSysCompParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/FrameFormatConfig.ts b/src/struct_frame/boilerplate/ts/FrameFormatConfig.ts index aa85962a..d0016a1b 100644 --- a/src/struct_frame/boilerplate/ts/FrameFormatConfig.ts +++ b/src/struct_frame/boilerplate/ts/FrameFormatConfig.ts @@ -1,158 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// FrameFormatConfig Frame Format +// FrameFormatConfig Frame Format Configuration // ============================================================================= -export enum FrameFormatConfigParserState { - LOOKING_FOR_START1 = 0, - LOOKING_FOR_START2 = 1, - GETTING_MSG_ID = 2, - GETTING_PAYLOAD = 3 -} +/** Configuration for FrameFormatConfig frame format */ +export const FrameFormatConfigConfig: FrameParserConfig = { + name: 'FrameFormatConfig', + startBytes: [0x90, 0x71], + headerSize: 2, + footerSize: 1, + hasLength: false, + lengthBytes: 0, + hasCrc: true, +}; /** * FrameFormatConfig - Frame format parser and encoder * * Format: [START_BYTE1=0x90] [START_BYTE2=0x71] [MSG_ID] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class FrameFormatConfig { - static readonly START_BYTE1 = 0x90; - static readonly START_BYTE2 = 0x71; - static readonly HEADER_SIZE = 2; - static readonly FOOTER_SIZE = 1; - static readonly OVERHEAD = 3; +export const FrameFormatConfig = createFrameParserClass(FrameFormatConfigConfig); - private state: FrameFormatConfigParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new FrameFormatConfig parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = FrameFormatConfigParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = FrameFormatConfigParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case FrameFormatConfigParserState.LOOKING_FOR_START1: - if (byte === FrameFormatConfig.START_BYTE1) { - this.buffer = [byte]; - this.state = FrameFormatConfigParserState.LOOKING_FOR_START2; - } - break; - - case FrameFormatConfigParserState.LOOKING_FOR_START2: - if (byte === FrameFormatConfig.START_BYTE2) { - this.buffer.push(byte); - this.state = FrameFormatConfigParserState.GETTING_MSG_ID; - } else if (byte === FrameFormatConfig.START_BYTE1) { - this.buffer = [byte]; - this.state = FrameFormatConfigParserState.LOOKING_FOR_START2; - } else { - this.state = FrameFormatConfigParserState.LOOKING_FOR_START1; - } - break; - - case FrameFormatConfigParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - if (this.get_msg_length) { - const msg_length = this.get_msg_length(byte); - if (msg_length !== undefined) { - this.packet_size = FrameFormatConfig.OVERHEAD + msg_length; - this.state = FrameFormatConfigParserState.GETTING_PAYLOAD; - } else { - this.state = FrameFormatConfigParserState.LOOKING_FOR_START1; - } - } else { - this.state = FrameFormatConfigParserState.LOOKING_FOR_START1; - } - break; - - case FrameFormatConfigParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, FrameFormatConfig.HEADER_SIZE, 0, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = FrameFormatConfigParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - /** - * Encode a message with FrameFormatConfig format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(FrameFormatConfig.START_BYTE1); - output.push(FrameFormatConfig.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 0, 2); - return new Uint8Array(output); - } - - /** - * Validate a complete FrameFormatConfig packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < FrameFormatConfig.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== FrameFormatConfig.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== FrameFormatConfig.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, FrameFormatConfig.HEADER_SIZE, 0, 2); - } -} +/** Parser state type alias for backward compatibility */ +export type FrameFormatConfigParserState = GenericParserState; +export { GenericParserState as FrameFormatConfigParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/MavlinkV1Frame.ts b/src/struct_frame/boilerplate/ts/MavlinkV1Frame.ts index 6fa25b04..d71b7a8f 100644 --- a/src/struct_frame/boilerplate/ts/MavlinkV1Frame.ts +++ b/src/struct_frame/boilerplate/ts/MavlinkV1Frame.ts @@ -1,142 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// MavlinkV1Frame Frame Format +// MavlinkV1Frame Frame Format Configuration // ============================================================================= -export enum MavlinkV1FrameParserState { - LOOKING_FOR_START = 0, - GETTING_MSG_ID = 1, - GETTING_LENGTH = 2, - GETTING_PAYLOAD = 3 -} +/** Configuration for MavlinkV1Frame frame format */ +export const MavlinkV1FrameConfig: FrameParserConfig = { + name: 'MavlinkV1Frame', + startBytes: [0xFE], + headerSize: 6, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, +}; /** * MavlinkV1Frame - Frame format parser and encoder * * Format: [STX=0xFE] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class MavlinkV1Frame { - static readonly START_BYTE = 0xFE; - static readonly HEADER_SIZE = 6; - static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 8; - static readonly LENGTH_BYTES = 1; +export const MavlinkV1Frame = createFrameParserClass(MavlinkV1FrameConfig); - private state: MavlinkV1FrameParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private msg_length: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new MavlinkV1Frame parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = MavlinkV1FrameParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = MavlinkV1FrameParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case MavlinkV1FrameParserState.LOOKING_FOR_START: - if (byte === MavlinkV1Frame.START_BYTE) { - this.buffer = [byte]; - this.state = MavlinkV1FrameParserState.GETTING_MSG_ID; - } - break; - - case MavlinkV1FrameParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = MavlinkV1FrameParserState.GETTING_LENGTH; - break; - - case MavlinkV1FrameParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = MavlinkV1Frame.OVERHEAD + this.msg_length; - this.state = MavlinkV1FrameParserState.GETTING_PAYLOAD; - break; - - case MavlinkV1FrameParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, MavlinkV1Frame.HEADER_SIZE, 1, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = MavlinkV1FrameParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - /** - * Encode a message with MavlinkV1Frame format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(MavlinkV1Frame.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1); - return new Uint8Array(output); - } - - /** - * Validate a complete MavlinkV1Frame packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < MavlinkV1Frame.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== MavlinkV1Frame.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, MavlinkV1Frame.HEADER_SIZE, 1, 1); - } -} +/** Parser state type alias for backward compatibility */ +export type MavlinkV1FrameParserState = GenericParserState; +export { GenericParserState as MavlinkV1FrameParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/MavlinkV2Frame.ts b/src/struct_frame/boilerplate/ts/MavlinkV2Frame.ts index 1c5bdef9..265839e4 100644 --- a/src/struct_frame/boilerplate/ts/MavlinkV2Frame.ts +++ b/src/struct_frame/boilerplate/ts/MavlinkV2Frame.ts @@ -1,142 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// MavlinkV2Frame Frame Format +// MavlinkV2Frame Frame Format Configuration // ============================================================================= -export enum MavlinkV2FrameParserState { - LOOKING_FOR_START = 0, - GETTING_MSG_ID = 1, - GETTING_LENGTH = 2, - GETTING_PAYLOAD = 3 -} +/** Configuration for MavlinkV2Frame frame format */ +export const MavlinkV2FrameConfig: FrameParserConfig = { + name: 'MavlinkV2Frame', + startBytes: [0xFD], + headerSize: 8, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, +}; /** * MavlinkV2Frame - Frame format parser and encoder * * Format: [STX=0xFD] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class MavlinkV2Frame { - static readonly START_BYTE = 0xFD; - static readonly HEADER_SIZE = 8; - static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 10; - static readonly LENGTH_BYTES = 1; +export const MavlinkV2Frame = createFrameParserClass(MavlinkV2FrameConfig); - private state: MavlinkV2FrameParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private msg_length: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new MavlinkV2Frame parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = MavlinkV2FrameParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = MavlinkV2FrameParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case MavlinkV2FrameParserState.LOOKING_FOR_START: - if (byte === MavlinkV2Frame.START_BYTE) { - this.buffer = [byte]; - this.state = MavlinkV2FrameParserState.GETTING_MSG_ID; - } - break; - - case MavlinkV2FrameParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = MavlinkV2FrameParserState.GETTING_LENGTH; - break; - - case MavlinkV2FrameParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = MavlinkV2Frame.OVERHEAD + this.msg_length; - this.state = MavlinkV2FrameParserState.GETTING_PAYLOAD; - break; - - case MavlinkV2FrameParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, MavlinkV2Frame.HEADER_SIZE, 1, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = MavlinkV2FrameParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - /** - * Encode a message with MavlinkV2Frame format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(MavlinkV2Frame.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1); - return new Uint8Array(output); - } - - /** - * Validate a complete MavlinkV2Frame packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < MavlinkV2Frame.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== MavlinkV2Frame.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, MavlinkV2Frame.HEADER_SIZE, 1, 1); - } -} +/** Parser state type alias for backward compatibility */ +export type MavlinkV2FrameParserState = GenericParserState; +export { GenericParserState as MavlinkV2FrameParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/TinyDefault.ts b/src/struct_frame/boilerplate/ts/TinyDefault.ts index 66f376a2..6b312e2e 100644 --- a/src/struct_frame/boilerplate/ts/TinyDefault.ts +++ b/src/struct_frame/boilerplate/ts/TinyDefault.ts @@ -1,142 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// TinyDefault Frame Format +// TinyDefault Frame Format Configuration // ============================================================================= -export enum TinyDefaultParserState { - LOOKING_FOR_START = 0, - GETTING_MSG_ID = 1, - GETTING_LENGTH = 2, - GETTING_PAYLOAD = 3 -} +/** Configuration for TinyDefault frame format */ +export const TinyDefaultConfig: FrameParserConfig = { + name: 'TinyDefault', + startBytes: [0x71], + headerSize: 3, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, +}; /** * TinyDefault - Frame format parser and encoder * * Format: [START_BYTE=0x71] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class TinyDefault { - static readonly START_BYTE = 0x71; - static readonly HEADER_SIZE = 3; - static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 5; - static readonly LENGTH_BYTES = 1; +export const TinyDefault = createFrameParserClass(TinyDefaultConfig); - private state: TinyDefaultParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private msg_length: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new TinyDefault parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = TinyDefaultParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = TinyDefaultParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case TinyDefaultParserState.LOOKING_FOR_START: - if (byte === TinyDefault.START_BYTE) { - this.buffer = [byte]; - this.state = TinyDefaultParserState.GETTING_MSG_ID; - } - break; - - case TinyDefaultParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = TinyDefaultParserState.GETTING_LENGTH; - break; - - case TinyDefaultParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = TinyDefault.OVERHEAD + this.msg_length; - this.state = TinyDefaultParserState.GETTING_PAYLOAD; - break; - - case TinyDefaultParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, TinyDefault.HEADER_SIZE, 1, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = TinyDefaultParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - /** - * Encode a message with TinyDefault format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(TinyDefault.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1); - return new Uint8Array(output); - } - - /** - * Validate a complete TinyDefault packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < TinyDefault.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== TinyDefault.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinyDefault.HEADER_SIZE, 1, 1); - } -} +/** Parser state type alias for backward compatibility */ +export type TinyDefaultParserState = GenericParserState; +export { GenericParserState as TinyDefaultParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/TinyExtended.ts b/src/struct_frame/boilerplate/ts/TinyExtended.ts index 67d69c4e..7d504a31 100644 --- a/src/struct_frame/boilerplate/ts/TinyExtended.ts +++ b/src/struct_frame/boilerplate/ts/TinyExtended.ts @@ -1,148 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// TinyExtended Frame Format +// TinyExtended Frame Format Configuration // ============================================================================= -export enum TinyExtendedParserState { - LOOKING_FOR_START = 0, - GETTING_MSG_ID = 1, - GETTING_LENGTH = 2, - GETTING_PAYLOAD = 3 -} +/** Configuration for TinyExtended frame format */ +export const TinyExtendedConfig: FrameParserConfig = { + name: 'TinyExtended', + startBytes: [0x74], + headerSize: 5, + footerSize: 2, + hasLength: true, + lengthBytes: 2, + hasCrc: true, +}; /** * TinyExtended - Frame format parser and encoder * * Format: [START_BYTE=0x74] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class TinyExtended { - static readonly START_BYTE = 0x74; - static readonly HEADER_SIZE = 5; - static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 7; - static readonly LENGTH_BYTES = 2; +export const TinyExtended = createFrameParserClass(TinyExtendedConfig); - private state: TinyExtendedParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private msg_length: number; - private length_lo: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new TinyExtended parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = TinyExtendedParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - this.length_lo = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = TinyExtendedParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case TinyExtendedParserState.LOOKING_FOR_START: - if (byte === TinyExtended.START_BYTE) { - this.buffer = [byte]; - this.state = TinyExtendedParserState.GETTING_MSG_ID; - } - break; - - case TinyExtendedParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = TinyExtendedParserState.GETTING_LENGTH; - break; - - case TinyExtendedParserState.GETTING_LENGTH: - this.buffer.push(byte); - if (this.buffer.length === 3) { - this.length_lo = byte; - } else { - this.msg_length = this.length_lo | (byte << 8); - this.packet_size = TinyExtended.OVERHEAD + this.msg_length; - this.state = TinyExtendedParserState.GETTING_PAYLOAD; - } - break; - - case TinyExtendedParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, TinyExtended.HEADER_SIZE, 2, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = TinyExtendedParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - /** - * Encode a message with TinyExtended format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(TinyExtended.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 2, 1); - return new Uint8Array(output); - } - - /** - * Validate a complete TinyExtended packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < TinyExtended.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== TinyExtended.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinyExtended.HEADER_SIZE, 2, 1); - } -} +/** Parser state type alias for backward compatibility */ +export type TinyExtendedParserState = GenericParserState; +export { GenericParserState as TinyExtendedParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/TinyExtendedLength.ts b/src/struct_frame/boilerplate/ts/TinyExtendedLength.ts index 54c81ac9..9326a099 100644 --- a/src/struct_frame/boilerplate/ts/TinyExtendedLength.ts +++ b/src/struct_frame/boilerplate/ts/TinyExtendedLength.ts @@ -1,148 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// TinyExtendedLength Frame Format +// TinyExtendedLength Frame Format Configuration // ============================================================================= -export enum TinyExtendedLengthParserState { - LOOKING_FOR_START = 0, - GETTING_MSG_ID = 1, - GETTING_LENGTH = 2, - GETTING_PAYLOAD = 3 -} +/** Configuration for TinyExtendedLength frame format */ +export const TinyExtendedLengthConfig: FrameParserConfig = { + name: 'TinyExtendedLength', + startBytes: [0x73], + headerSize: 4, + footerSize: 2, + hasLength: true, + lengthBytes: 2, + hasCrc: true, +}; /** * TinyExtendedLength - Frame format parser and encoder * * Format: [START_BYTE=0x73] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class TinyExtendedLength { - static readonly START_BYTE = 0x73; - static readonly HEADER_SIZE = 4; - static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 6; - static readonly LENGTH_BYTES = 2; +export const TinyExtendedLength = createFrameParserClass(TinyExtendedLengthConfig); - private state: TinyExtendedLengthParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private msg_length: number; - private length_lo: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new TinyExtendedLength parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = TinyExtendedLengthParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - this.length_lo = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = TinyExtendedLengthParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case TinyExtendedLengthParserState.LOOKING_FOR_START: - if (byte === TinyExtendedLength.START_BYTE) { - this.buffer = [byte]; - this.state = TinyExtendedLengthParserState.GETTING_MSG_ID; - } - break; - - case TinyExtendedLengthParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = TinyExtendedLengthParserState.GETTING_LENGTH; - break; - - case TinyExtendedLengthParserState.GETTING_LENGTH: - this.buffer.push(byte); - if (this.buffer.length === 3) { - this.length_lo = byte; - } else { - this.msg_length = this.length_lo | (byte << 8); - this.packet_size = TinyExtendedLength.OVERHEAD + this.msg_length; - this.state = TinyExtendedLengthParserState.GETTING_PAYLOAD; - } - break; - - case TinyExtendedLengthParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, TinyExtendedLength.HEADER_SIZE, 2, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = TinyExtendedLengthParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - /** - * Encode a message with TinyExtendedLength format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(TinyExtendedLength.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 2, 1); - return new Uint8Array(output); - } - - /** - * Validate a complete TinyExtendedLength packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < TinyExtendedLength.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== TinyExtendedLength.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinyExtendedLength.HEADER_SIZE, 2, 1); - } -} +/** Parser state type alias for backward compatibility */ +export type TinyExtendedLengthParserState = GenericParserState; +export { GenericParserState as TinyExtendedLengthParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/TinyExtendedMsgIds.ts b/src/struct_frame/boilerplate/ts/TinyExtendedMsgIds.ts index 32d573cb..e938eb1d 100644 --- a/src/struct_frame/boilerplate/ts/TinyExtendedMsgIds.ts +++ b/src/struct_frame/boilerplate/ts/TinyExtendedMsgIds.ts @@ -1,142 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// TinyExtendedMsgIds Frame Format +// TinyExtendedMsgIds Frame Format Configuration // ============================================================================= -export enum TinyExtendedMsgIdsParserState { - LOOKING_FOR_START = 0, - GETTING_MSG_ID = 1, - GETTING_LENGTH = 2, - GETTING_PAYLOAD = 3 -} +/** Configuration for TinyExtendedMsgIds frame format */ +export const TinyExtendedMsgIdsConfig: FrameParserConfig = { + name: 'TinyExtendedMsgIds', + startBytes: [0x72], + headerSize: 4, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, +}; /** * TinyExtendedMsgIds - Frame format parser and encoder * * Format: [START_BYTE=0x72] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class TinyExtendedMsgIds { - static readonly START_BYTE = 0x72; - static readonly HEADER_SIZE = 4; - static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 6; - static readonly LENGTH_BYTES = 1; +export const TinyExtendedMsgIds = createFrameParserClass(TinyExtendedMsgIdsConfig); - private state: TinyExtendedMsgIdsParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private msg_length: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new TinyExtendedMsgIds parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = TinyExtendedMsgIdsParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = TinyExtendedMsgIdsParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case TinyExtendedMsgIdsParserState.LOOKING_FOR_START: - if (byte === TinyExtendedMsgIds.START_BYTE) { - this.buffer = [byte]; - this.state = TinyExtendedMsgIdsParserState.GETTING_MSG_ID; - } - break; - - case TinyExtendedMsgIdsParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = TinyExtendedMsgIdsParserState.GETTING_LENGTH; - break; - - case TinyExtendedMsgIdsParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = TinyExtendedMsgIds.OVERHEAD + this.msg_length; - this.state = TinyExtendedMsgIdsParserState.GETTING_PAYLOAD; - break; - - case TinyExtendedMsgIdsParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, TinyExtendedMsgIds.HEADER_SIZE, 1, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = TinyExtendedMsgIdsParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - /** - * Encode a message with TinyExtendedMsgIds format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(TinyExtendedMsgIds.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1); - return new Uint8Array(output); - } - - /** - * Validate a complete TinyExtendedMsgIds packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < TinyExtendedMsgIds.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== TinyExtendedMsgIds.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinyExtendedMsgIds.HEADER_SIZE, 1, 1); - } -} +/** Parser state type alias for backward compatibility */ +export type TinyExtendedMsgIdsParserState = GenericParserState; +export { GenericParserState as TinyExtendedMsgIdsParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/TinyExtendedMultiSystemStream.ts b/src/struct_frame/boilerplate/ts/TinyExtendedMultiSystemStream.ts index e399e197..35a79adb 100644 --- a/src/struct_frame/boilerplate/ts/TinyExtendedMultiSystemStream.ts +++ b/src/struct_frame/boilerplate/ts/TinyExtendedMultiSystemStream.ts @@ -1,148 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// TinyExtendedMultiSystemStream Frame Format +// TinyExtendedMultiSystemStream Frame Format Configuration // ============================================================================= -export enum TinyExtendedMultiSystemStreamParserState { - LOOKING_FOR_START = 0, - GETTING_MSG_ID = 1, - GETTING_LENGTH = 2, - GETTING_PAYLOAD = 3 -} +/** Configuration for TinyExtendedMultiSystemStream frame format */ +export const TinyExtendedMultiSystemStreamConfig: FrameParserConfig = { + name: 'TinyExtendedMultiSystemStream', + startBytes: [0x78], + headerSize: 8, + footerSize: 2, + hasLength: true, + lengthBytes: 2, + hasCrc: true, +}; /** * TinyExtendedMultiSystemStream - Frame format parser and encoder * * Format: [START_BYTE=0x78] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class TinyExtendedMultiSystemStream { - static readonly START_BYTE = 0x78; - static readonly HEADER_SIZE = 8; - static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 10; - static readonly LENGTH_BYTES = 2; +export const TinyExtendedMultiSystemStream = createFrameParserClass(TinyExtendedMultiSystemStreamConfig); - private state: TinyExtendedMultiSystemStreamParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private msg_length: number; - private length_lo: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new TinyExtendedMultiSystemStream parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - this.length_lo = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START: - if (byte === TinyExtendedMultiSystemStream.START_BYTE) { - this.buffer = [byte]; - this.state = TinyExtendedMultiSystemStreamParserState.GETTING_MSG_ID; - } - break; - - case TinyExtendedMultiSystemStreamParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = TinyExtendedMultiSystemStreamParserState.GETTING_LENGTH; - break; - - case TinyExtendedMultiSystemStreamParserState.GETTING_LENGTH: - this.buffer.push(byte); - if (this.buffer.length === 3) { - this.length_lo = byte; - } else { - this.msg_length = this.length_lo | (byte << 8); - this.packet_size = TinyExtendedMultiSystemStream.OVERHEAD + this.msg_length; - this.state = TinyExtendedMultiSystemStreamParserState.GETTING_PAYLOAD; - } - break; - - case TinyExtendedMultiSystemStreamParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, TinyExtendedMultiSystemStream.HEADER_SIZE, 2, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - /** - * Encode a message with TinyExtendedMultiSystemStream format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(TinyExtendedMultiSystemStream.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 2, 1); - return new Uint8Array(output); - } - - /** - * Validate a complete TinyExtendedMultiSystemStream packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < TinyExtendedMultiSystemStream.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== TinyExtendedMultiSystemStream.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinyExtendedMultiSystemStream.HEADER_SIZE, 2, 1); - } -} +/** Parser state type alias for backward compatibility */ +export type TinyExtendedMultiSystemStreamParserState = GenericParserState; +export { GenericParserState as TinyExtendedMultiSystemStreamParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/TinyMinimal.ts b/src/struct_frame/boilerplate/ts/TinyMinimal.ts index f8748f59..51c5a920 100644 --- a/src/struct_frame/boilerplate/ts/TinyMinimal.ts +++ b/src/struct_frame/boilerplate/ts/TinyMinimal.ts @@ -1,138 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// TinyMinimal Frame Format +// TinyMinimal Frame Format Configuration // ============================================================================= -export enum TinyMinimalParserState { - LOOKING_FOR_START = 0, - GETTING_MSG_ID = 1, - GETTING_PAYLOAD = 2 -} +/** Configuration for TinyMinimal frame format */ +export const TinyMinimalConfig: FrameParserConfig = { + name: 'TinyMinimal', + startBytes: [0x70], + headerSize: 2, + footerSize: 0, + hasLength: false, + lengthBytes: 0, + hasCrc: false, +}; /** * TinyMinimal - Frame format parser and encoder * * Format: [START_BYTE=0x70] [MSG_ID] [MSG...] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class TinyMinimal { - static readonly START_BYTE = 0x70; - static readonly HEADER_SIZE = 2; - static readonly FOOTER_SIZE = 0; - static readonly OVERHEAD = 2; +export const TinyMinimal = createFrameParserClass(TinyMinimalConfig); - private state: TinyMinimalParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new TinyMinimal parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = TinyMinimalParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = TinyMinimalParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case TinyMinimalParserState.LOOKING_FOR_START: - if (byte === TinyMinimal.START_BYTE) { - this.buffer = [byte]; - this.state = TinyMinimalParserState.GETTING_MSG_ID; - } - break; - - case TinyMinimalParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - if (this.get_msg_length) { - const msg_length = this.get_msg_length(byte); - if (msg_length !== undefined) { - this.packet_size = TinyMinimal.OVERHEAD + msg_length; - this.state = TinyMinimalParserState.GETTING_PAYLOAD; - } else { - this.state = TinyMinimalParserState.LOOKING_FOR_START; - } - } else { - this.state = TinyMinimalParserState.LOOKING_FOR_START; - } - break; - - case TinyMinimalParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared minimal payload validation - const validationResult = validate_payload_minimal(this.buffer, TinyMinimal.HEADER_SIZE); - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - this.state = TinyMinimalParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - /** - * Encode a message with TinyMinimal format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(TinyMinimal.START_BYTE); - // Use shared minimal payload encoding - encode_payload_minimal(output, msg_id, msg); - return new Uint8Array(output); - } - - /** - * Validate a complete TinyMinimal packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < TinyMinimal.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== TinyMinimal.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared minimal payload validation - return validate_payload_minimal(buffer, TinyMinimal.HEADER_SIZE); - } -} +/** Parser state type alias for backward compatibility */ +export type TinyMinimalParserState = GenericParserState; +export { GenericParserState as TinyMinimalParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/TinyMultiSystemStream.ts b/src/struct_frame/boilerplate/ts/TinyMultiSystemStream.ts index e14cb78a..d4fe9a3d 100644 --- a/src/struct_frame/boilerplate/ts/TinyMultiSystemStream.ts +++ b/src/struct_frame/boilerplate/ts/TinyMultiSystemStream.ts @@ -1,142 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// TinyMultiSystemStream Frame Format +// TinyMultiSystemStream Frame Format Configuration // ============================================================================= -export enum TinyMultiSystemStreamParserState { - LOOKING_FOR_START = 0, - GETTING_MSG_ID = 1, - GETTING_LENGTH = 2, - GETTING_PAYLOAD = 3 -} +/** Configuration for TinyMultiSystemStream frame format */ +export const TinyMultiSystemStreamConfig: FrameParserConfig = { + name: 'TinyMultiSystemStream', + startBytes: [0x77], + headerSize: 6, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, +}; /** * TinyMultiSystemStream - Frame format parser and encoder * * Format: [START_BYTE=0x77] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class TinyMultiSystemStream { - static readonly START_BYTE = 0x77; - static readonly HEADER_SIZE = 6; - static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 8; - static readonly LENGTH_BYTES = 1; +export const TinyMultiSystemStream = createFrameParserClass(TinyMultiSystemStreamConfig); - private state: TinyMultiSystemStreamParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private msg_length: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new TinyMultiSystemStream parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = TinyMultiSystemStreamParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = TinyMultiSystemStreamParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case TinyMultiSystemStreamParserState.LOOKING_FOR_START: - if (byte === TinyMultiSystemStream.START_BYTE) { - this.buffer = [byte]; - this.state = TinyMultiSystemStreamParserState.GETTING_MSG_ID; - } - break; - - case TinyMultiSystemStreamParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = TinyMultiSystemStreamParserState.GETTING_LENGTH; - break; - - case TinyMultiSystemStreamParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = TinyMultiSystemStream.OVERHEAD + this.msg_length; - this.state = TinyMultiSystemStreamParserState.GETTING_PAYLOAD; - break; - - case TinyMultiSystemStreamParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, TinyMultiSystemStream.HEADER_SIZE, 1, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = TinyMultiSystemStreamParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - /** - * Encode a message with TinyMultiSystemStream format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(TinyMultiSystemStream.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1); - return new Uint8Array(output); - } - - /** - * Validate a complete TinyMultiSystemStream packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < TinyMultiSystemStream.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== TinyMultiSystemStream.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinyMultiSystemStream.HEADER_SIZE, 1, 1); - } -} +/** Parser state type alias for backward compatibility */ +export type TinyMultiSystemStreamParserState = GenericParserState; +export { GenericParserState as TinyMultiSystemStreamParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/TinySeq.ts b/src/struct_frame/boilerplate/ts/TinySeq.ts index f65ba648..b78dd9f1 100644 --- a/src/struct_frame/boilerplate/ts/TinySeq.ts +++ b/src/struct_frame/boilerplate/ts/TinySeq.ts @@ -1,142 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// TinySeq Frame Format +// TinySeq Frame Format Configuration // ============================================================================= -export enum TinySeqParserState { - LOOKING_FOR_START = 0, - GETTING_MSG_ID = 1, - GETTING_LENGTH = 2, - GETTING_PAYLOAD = 3 -} +/** Configuration for TinySeq frame format */ +export const TinySeqConfig: FrameParserConfig = { + name: 'TinySeq', + startBytes: [0x76], + headerSize: 4, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, +}; /** * TinySeq - Frame format parser and encoder * * Format: [START_BYTE=0x76] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class TinySeq { - static readonly START_BYTE = 0x76; - static readonly HEADER_SIZE = 4; - static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 6; - static readonly LENGTH_BYTES = 1; +export const TinySeq = createFrameParserClass(TinySeqConfig); - private state: TinySeqParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private msg_length: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new TinySeq parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = TinySeqParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = TinySeqParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case TinySeqParserState.LOOKING_FOR_START: - if (byte === TinySeq.START_BYTE) { - this.buffer = [byte]; - this.state = TinySeqParserState.GETTING_MSG_ID; - } - break; - - case TinySeqParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = TinySeqParserState.GETTING_LENGTH; - break; - - case TinySeqParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = TinySeq.OVERHEAD + this.msg_length; - this.state = TinySeqParserState.GETTING_PAYLOAD; - break; - - case TinySeqParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, TinySeq.HEADER_SIZE, 1, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = TinySeqParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - /** - * Encode a message with TinySeq format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(TinySeq.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1); - return new Uint8Array(output); - } - - /** - * Validate a complete TinySeq packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < TinySeq.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== TinySeq.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinySeq.HEADER_SIZE, 1, 1); - } -} +/** Parser state type alias for backward compatibility */ +export type TinySeqParserState = GenericParserState; +export { GenericParserState as TinySeqParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/TinySysComp.ts b/src/struct_frame/boilerplate/ts/TinySysComp.ts index bc77aa29..1f55713e 100644 --- a/src/struct_frame/boilerplate/ts/TinySysComp.ts +++ b/src/struct_frame/boilerplate/ts/TinySysComp.ts @@ -1,142 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// TinySysComp Frame Format +// TinySysComp Frame Format Configuration // ============================================================================= -export enum TinySysCompParserState { - LOOKING_FOR_START = 0, - GETTING_MSG_ID = 1, - GETTING_LENGTH = 2, - GETTING_PAYLOAD = 3 -} +/** Configuration for TinySysComp frame format */ +export const TinySysCompConfig: FrameParserConfig = { + name: 'TinySysComp', + startBytes: [0x75], + headerSize: 5, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, +}; /** * TinySysComp - Frame format parser and encoder * * Format: [START_BYTE=0x75] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class TinySysComp { - static readonly START_BYTE = 0x75; - static readonly HEADER_SIZE = 5; - static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 7; - static readonly LENGTH_BYTES = 1; +export const TinySysComp = createFrameParserClass(TinySysCompConfig); - private state: TinySysCompParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private msg_length: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new TinySysComp parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = TinySysCompParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = TinySysCompParserState.LOOKING_FOR_START; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case TinySysCompParserState.LOOKING_FOR_START: - if (byte === TinySysComp.START_BYTE) { - this.buffer = [byte]; - this.state = TinySysCompParserState.GETTING_MSG_ID; - } - break; - - case TinySysCompParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = TinySysCompParserState.GETTING_LENGTH; - break; - - case TinySysCompParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = TinySysComp.OVERHEAD + this.msg_length; - this.state = TinySysCompParserState.GETTING_PAYLOAD; - break; - - case TinySysCompParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, TinySysComp.HEADER_SIZE, 1, 1); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = TinySysCompParserState.LOOKING_FOR_START; - } - break; - } - - return result; - } - - /** - * Encode a message with TinySysComp format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(TinySysComp.START_BYTE); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 1); - return new Uint8Array(output); - } - - /** - * Validate a complete TinySysComp packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < TinySysComp.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== TinySysComp.START_BYTE) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, TinySysComp.HEADER_SIZE, 1, 1); - } -} +/** Parser state type alias for backward compatibility */ +export type TinySysCompParserState = GenericParserState; +export { GenericParserState as TinySysCompParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/UbxFrame.ts b/src/struct_frame/boilerplate/ts/UbxFrame.ts index 84d8634a..173bf7a4 100644 --- a/src/struct_frame/boilerplate/ts/UbxFrame.ts +++ b/src/struct_frame/boilerplate/ts/UbxFrame.ts @@ -1,160 +1,34 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. import { - FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, - validate_payload_with_crc, validate_payload_minimal, - encode_payload_with_crc, encode_payload_minimal, + FrameParserConfig, createFrameParserClass, GenericParserState, } from './frame_base'; // ============================================================================= -// UbxFrame Frame Format +// UbxFrame Frame Format Configuration // ============================================================================= -export enum UbxFrameParserState { - LOOKING_FOR_START1 = 0, - LOOKING_FOR_START2 = 1, - GETTING_MSG_ID = 2, - GETTING_LENGTH = 3, - GETTING_PAYLOAD = 4 -} +/** Configuration for UbxFrame frame format */ +export const UbxFrameConfig: FrameParserConfig = { + name: 'UbxFrame', + startBytes: [0xB5, 0x62], + headerSize: 5, + footerSize: 2, + hasLength: true, + lengthBytes: 1, + hasCrc: true, +}; /** * UbxFrame - Frame format parser and encoder * * Format: [SYNC1=0xB5] [SYNC2=0x62] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + * + * This class is generated using createFrameParserClass() for code reuse. */ -export class UbxFrame { - static readonly START_BYTE1 = 0xB5; - static readonly START_BYTE2 = 0x62; - static readonly HEADER_SIZE = 5; - static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 7; - static readonly LENGTH_BYTES = 1; +export const UbxFrame = createFrameParserClass(UbxFrameConfig); - private state: UbxFrameParserState; - private buffer: number[]; - private packet_size: number; - private msg_id: number; - private msg_length: number; - private get_msg_length?: (msg_id: number) => number | undefined; - - /** - * Create a new UbxFrame parser - * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) - */ - constructor(get_msg_length?: (msg_id: number) => number | undefined) { - this.get_msg_length = get_msg_length; - this.state = UbxFrameParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** Reset parser state */ - reset(): void { - this.state = UbxFrameParserState.LOOKING_FOR_START1; - this.buffer = []; - this.packet_size = 0; - this.msg_id = 0; - this.msg_length = 0; - } - - /** - * Parse a single byte - * @param byte The byte to parse - * @returns FrameMsgInfo with valid=true when a complete valid message is received - */ - parse_byte(byte: number): FrameMsgInfo { - const result = createFrameMsgInfo(); - - switch (this.state) { - case UbxFrameParserState.LOOKING_FOR_START1: - if (byte === UbxFrame.START_BYTE1) { - this.buffer = [byte]; - this.state = UbxFrameParserState.LOOKING_FOR_START2; - } - break; - - case UbxFrameParserState.LOOKING_FOR_START2: - if (byte === UbxFrame.START_BYTE2) { - this.buffer.push(byte); - this.state = UbxFrameParserState.GETTING_MSG_ID; - } else if (byte === UbxFrame.START_BYTE1) { - this.buffer = [byte]; - this.state = UbxFrameParserState.LOOKING_FOR_START2; - } else { - this.state = UbxFrameParserState.LOOKING_FOR_START1; - } - break; - - case UbxFrameParserState.GETTING_MSG_ID: - this.buffer.push(byte); - this.msg_id = byte; - this.state = UbxFrameParserState.GETTING_LENGTH; - break; - - case UbxFrameParserState.GETTING_LENGTH: - this.buffer.push(byte); - this.msg_length = byte; - this.packet_size = UbxFrame.OVERHEAD + this.msg_length; - this.state = UbxFrameParserState.GETTING_PAYLOAD; - break; - - case UbxFrameParserState.GETTING_PAYLOAD: - this.buffer.push(byte); - - if (this.buffer.length >= this.packet_size) { - // Use shared payload validation with CRC - const validationResult = validate_payload_with_crc(this.buffer, UbxFrame.HEADER_SIZE, 1, 2); - if (validationResult.valid) { - result.valid = validationResult.valid; - result.msg_id = validationResult.msg_id; - result.msg_len = validationResult.msg_len; - result.msg_data = validationResult.msg_data; - } - this.state = UbxFrameParserState.LOOKING_FOR_START1; - } - break; - } - - return result; - } - - /** - * Encode a message with UbxFrame format - * @param msg_id Message ID - * @param msg Message data - * @returns Encoded frame as Uint8Array - */ - static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { - const output: number[] = []; - output.push(UbxFrame.START_BYTE1); - output.push(UbxFrame.START_BYTE2); - // Use shared payload encoding with CRC - encode_payload_with_crc(output, msg_id, msg, 1, 2); - return new Uint8Array(output); - } - - /** - * Validate a complete UbxFrame packet in a buffer - * @param buffer Buffer containing the complete packet - * @returns FrameMsgInfo with valid=true if packet is valid - */ - static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { - if (buffer.length < UbxFrame.OVERHEAD) { - return createFrameMsgInfo(); - } - - if (buffer[0] !== UbxFrame.START_BYTE1) { - return createFrameMsgInfo(); - } - if (buffer[1] !== UbxFrame.START_BYTE2) { - return createFrameMsgInfo(); - } - - // Use shared payload validation with CRC - return validate_payload_with_crc(buffer, UbxFrame.HEADER_SIZE, 1, 2); - } -} +/** Parser state type alias for backward compatibility */ +export type UbxFrameParserState = GenericParserState; +export { GenericParserState as UbxFrameParserState_Enum }; diff --git a/src/struct_frame/boilerplate/ts/frame_base.ts b/src/struct_frame/boilerplate/ts/frame_base.ts index fb26a9ec..7c369898 100644 --- a/src/struct_frame/boilerplate/ts/frame_base.ts +++ b/src/struct_frame/boilerplate/ts/frame_base.ts @@ -1,5 +1,5 @@ // Automatically generated frame parser base utilities -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. // Frame format type enumeration export enum FrameFormatType { @@ -62,6 +62,31 @@ export function createFrameMsgInfo(): FrameMsgInfo { }; } +// ============================================================================= +// Frame Format Configuration +// ============================================================================= + +/** + * Configuration interface for frame format parsers. + * This allows code reuse through configuration instead of code generation. + */ +export interface FrameParserConfig { + /** Name of the frame format (e.g., 'BasicDefault', 'TinyMinimal') */ + readonly name: string; + /** Start byte values (0, 1, or 2 bytes) */ + readonly startBytes: readonly number[]; + /** Total header size in bytes */ + readonly headerSize: number; + /** Total footer size in bytes (usually 0 or 2 for CRC) */ + readonly footerSize: number; + /** Whether this format includes a length field */ + readonly hasLength: boolean; + /** Number of bytes for length field (1 or 2) */ + readonly lengthBytes: number; + /** Whether this format includes CRC */ + readonly hasCrc: boolean; +} + // ============================================================================= // Shared Payload Parsing Functions // ============================================================================= @@ -168,3 +193,232 @@ export function encode_payload_minimal( output.push(msg[i]); } } + +// ============================================================================= +// Generic Frame Parser +// ============================================================================= +// This class provides a reusable frame parser that can be configured +// for different frame formats, reducing code duplication. + +/** Parser state enumeration */ +export enum GenericParserState { + LOOKING_FOR_START1 = 0, + LOOKING_FOR_START2 = 1, + GETTING_MSG_ID = 2, + GETTING_LENGTH = 3, + GETTING_PAYLOAD = 4 +} + +/** + * Generic frame parser that works with any frame format configuration. + * This class eliminates the need for separate parser classes per format. + */ +export class GenericFrameParser { + readonly config: FrameParserConfig; + + private state: GenericParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private msg_length: number; + private length_lo: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + constructor(config: FrameParserConfig, get_msg_length?: (msg_id: number) => number | undefined) { + this.config = config; + this.get_msg_length = get_msg_length; + this.state = this.getInitialState(); + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + private getInitialState(): GenericParserState { + if (this.config.startBytes.length === 0) { + return GenericParserState.GETTING_MSG_ID; + } else if (this.config.startBytes.length === 1) { + return GenericParserState.LOOKING_FOR_START1; + } else { + return GenericParserState.LOOKING_FOR_START1; + } + } + + reset(): void { + this.state = this.getInitialState(); + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + const startBytes = this.config.startBytes; + const overhead = this.config.headerSize + this.config.footerSize; + + switch (this.state) { + case GenericParserState.LOOKING_FOR_START1: + if (byte === startBytes[0]) { + this.buffer = [byte]; + if (startBytes.length > 1) { + this.state = GenericParserState.LOOKING_FOR_START2; + } else { + this.state = GenericParserState.GETTING_MSG_ID; + } + } + break; + + case GenericParserState.LOOKING_FOR_START2: + if (byte === startBytes[1]) { + this.buffer.push(byte); + this.state = GenericParserState.GETTING_MSG_ID; + } else if (byte === startBytes[0]) { + this.buffer = [byte]; + // Stay in LOOKING_FOR_START2 + } else { + this.state = GenericParserState.LOOKING_FOR_START1; + } + break; + + case GenericParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + if (this.config.hasLength) { + this.state = GenericParserState.GETTING_LENGTH; + } else if (this.get_msg_length) { + const msgLen = this.get_msg_length(byte); + if (msgLen !== undefined) { + this.packet_size = overhead + msgLen; + this.state = GenericParserState.GETTING_PAYLOAD; + } else { + this.state = this.getInitialState(); + } + } else { + this.state = this.getInitialState(); + } + break; + + case GenericParserState.GETTING_LENGTH: + this.buffer.push(byte); + if (this.config.lengthBytes === 1) { + this.msg_length = byte; + this.packet_size = overhead + this.msg_length; + this.state = GenericParserState.GETTING_PAYLOAD; + } else { + // 2-byte length + if (this.buffer.length === startBytes.length + 2) { + this.length_lo = byte; + } else { + this.msg_length = this.length_lo | (byte << 8); + this.packet_size = overhead + this.msg_length; + this.state = GenericParserState.GETTING_PAYLOAD; + } + } + break; + + case GenericParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + if (this.buffer.length >= this.packet_size) { + if (this.config.hasCrc) { + const validationResult = validate_payload_with_crc( + this.buffer, this.config.headerSize, this.config.lengthBytes, startBytes.length); + if (validationResult.valid) { + result.valid = validationResult.valid; + result.msg_id = validationResult.msg_id; + result.msg_len = validationResult.msg_len; + result.msg_data = validationResult.msg_data; + } + } else { + const validationResult = validate_payload_minimal(this.buffer, this.config.headerSize); + result.valid = validationResult.valid; + result.msg_id = validationResult.msg_id; + result.msg_len = validationResult.msg_len; + result.msg_data = validationResult.msg_data; + } + this.state = this.getInitialState(); + } + break; + } + + return result; + } + + /** + * Encode a message using this format + */ + static encode(config: FrameParserConfig, msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + + // Add start bytes + for (const startByte of config.startBytes) { + output.push(startByte); + } + + // Use appropriate payload encoding + if (config.hasCrc) { + encode_payload_with_crc(output, msg_id, msg, config.lengthBytes, config.startBytes.length); + } else { + encode_payload_minimal(output, msg_id, msg); + } + + return new Uint8Array(output); + } + + /** + * Validate a complete packet buffer using this format + */ + static validate_packet(config: FrameParserConfig, buffer: Uint8Array | number[]): FrameMsgInfo { + const overhead = config.headerSize + config.footerSize; + + if (buffer.length < overhead) { + return createFrameMsgInfo(); + } + + // Check start bytes + for (let i = 0; i < config.startBytes.length; i++) { + if (buffer[i] !== config.startBytes[i]) { + return createFrameMsgInfo(); + } + } + + // Validate payload + if (config.hasCrc) { + return validate_payload_with_crc(buffer, config.headerSize, config.lengthBytes, config.startBytes.length); + } else { + return validate_payload_minimal(buffer, config.headerSize); + } + } +} + +/** + * Create a typed frame parser class for a specific configuration. + * This factory function provides type-safe wrappers around GenericFrameParser. + */ +export function createFrameParserClass(config: FrameParserConfig) { + return class extends GenericFrameParser { + // Static properties from config + static readonly START_BYTES = config.startBytes; + static readonly HEADER_SIZE = config.headerSize; + static readonly FOOTER_SIZE = config.footerSize; + static readonly OVERHEAD = config.headerSize + config.footerSize; + static readonly HAS_LENGTH = config.hasLength; + static readonly LENGTH_BYTES = config.lengthBytes; + static readonly HAS_CRC = config.hasCrc; + static readonly CONFIG = config; + + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + super(config, get_msg_length); + } + + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + return GenericFrameParser.encode(config, msg_id, msg); + } + + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + return GenericFrameParser.validate_packet(config, buffer); + } + }; +} diff --git a/src/struct_frame/boilerplate/ts/index.ts b/src/struct_frame/boilerplate/ts/index.ts index 8f54f20d..d88c692f 100644 --- a/src/struct_frame/boilerplate/ts/index.ts +++ b/src/struct_frame/boilerplate/ts/index.ts @@ -1,12 +1,18 @@ // Automatically generated frame parser package -// Generated by 0.0.1 at Thu Dec 4 20:27:20 2025. +// Generated by 0.0.1 at Thu Dec 4 22:44:11 2025. -// Base utilities +// Base utilities and generic parser infrastructure export { FrameFormatType, FrameMsgInfo, createFrameMsgInfo, fletcher_checksum, + // Configuration interface for code reuse + FrameParserConfig, + // Generic parser class (use createFrameParserClass for type-safe wrappers) + GenericFrameParser, + GenericParserState, + createFrameParserClass, // Shared payload parsing functions validate_payload_with_crc, validate_payload_minimal, @@ -14,26 +20,26 @@ export { encode_payload_minimal, } from './frame_base'; -// Individual frame format parsers -export { TinyMinimal, TinyMinimalParserState } from './TinyMinimal'; -export { TinyDefault, TinyDefaultParserState } from './TinyDefault'; -export { TinyExtendedMsgIds, TinyExtendedMsgIdsParserState } from './TinyExtendedMsgIds'; -export { TinyExtendedLength, TinyExtendedLengthParserState } from './TinyExtendedLength'; -export { TinyExtended, TinyExtendedParserState } from './TinyExtended'; -export { TinySysComp, TinySysCompParserState } from './TinySysComp'; -export { TinySeq, TinySeqParserState } from './TinySeq'; -export { TinyMultiSystemStream, TinyMultiSystemStreamParserState } from './TinyMultiSystemStream'; -export { TinyExtendedMultiSystemStream, TinyExtendedMultiSystemStreamParserState } from './TinyExtendedMultiSystemStream'; -export { BasicMinimal, BasicMinimalParserState } from './BasicMinimal'; -export { BasicDefault, BasicDefaultParserState } from './BasicDefault'; -export { BasicExtendedMsgIds, BasicExtendedMsgIdsParserState } from './BasicExtendedMsgIds'; -export { BasicExtendedLength, BasicExtendedLengthParserState } from './BasicExtendedLength'; -export { BasicExtended, BasicExtendedParserState } from './BasicExtended'; -export { BasicSysComp, BasicSysCompParserState } from './BasicSysComp'; -export { BasicSeq, BasicSeqParserState } from './BasicSeq'; -export { BasicMultiSystemStream, BasicMultiSystemStreamParserState } from './BasicMultiSystemStream'; -export { BasicExtendedMultiSystemStream, BasicExtendedMultiSystemStreamParserState } from './BasicExtendedMultiSystemStream'; -export { UbxFrame, UbxFrameParserState } from './UbxFrame'; -export { MavlinkV1Frame, MavlinkV1FrameParserState } from './MavlinkV1Frame'; -export { MavlinkV2Frame, MavlinkV2FrameParserState } from './MavlinkV2Frame'; -export { FrameFormatConfig, FrameFormatConfigParserState } from './FrameFormatConfig'; +// Individual frame format parsers (configuration-based) +export { TinyMinimal, TinyMinimalConfig, TinyMinimalParserState } from './TinyMinimal'; +export { TinyDefault, TinyDefaultConfig, TinyDefaultParserState } from './TinyDefault'; +export { TinyExtendedMsgIds, TinyExtendedMsgIdsConfig, TinyExtendedMsgIdsParserState } from './TinyExtendedMsgIds'; +export { TinyExtendedLength, TinyExtendedLengthConfig, TinyExtendedLengthParserState } from './TinyExtendedLength'; +export { TinyExtended, TinyExtendedConfig, TinyExtendedParserState } from './TinyExtended'; +export { TinySysComp, TinySysCompConfig, TinySysCompParserState } from './TinySysComp'; +export { TinySeq, TinySeqConfig, TinySeqParserState } from './TinySeq'; +export { TinyMultiSystemStream, TinyMultiSystemStreamConfig, TinyMultiSystemStreamParserState } from './TinyMultiSystemStream'; +export { TinyExtendedMultiSystemStream, TinyExtendedMultiSystemStreamConfig, TinyExtendedMultiSystemStreamParserState } from './TinyExtendedMultiSystemStream'; +export { BasicMinimal, BasicMinimalConfig, BasicMinimalParserState } from './BasicMinimal'; +export { BasicDefault, BasicDefaultConfig, BasicDefaultParserState } from './BasicDefault'; +export { BasicExtendedMsgIds, BasicExtendedMsgIdsConfig, BasicExtendedMsgIdsParserState } from './BasicExtendedMsgIds'; +export { BasicExtendedLength, BasicExtendedLengthConfig, BasicExtendedLengthParserState } from './BasicExtendedLength'; +export { BasicExtended, BasicExtendedConfig, BasicExtendedParserState } from './BasicExtended'; +export { BasicSysComp, BasicSysCompConfig, BasicSysCompParserState } from './BasicSysComp'; +export { BasicSeq, BasicSeqConfig, BasicSeqParserState } from './BasicSeq'; +export { BasicMultiSystemStream, BasicMultiSystemStreamConfig, BasicMultiSystemStreamParserState } from './BasicMultiSystemStream'; +export { BasicExtendedMultiSystemStream, BasicExtendedMultiSystemStreamConfig, BasicExtendedMultiSystemStreamParserState } from './BasicExtendedMultiSystemStream'; +export { UbxFrame, UbxFrameConfig, UbxFrameParserState } from './UbxFrame'; +export { MavlinkV1Frame, MavlinkV1FrameConfig, MavlinkV1FrameParserState } from './MavlinkV1Frame'; +export { MavlinkV2Frame, MavlinkV2FrameConfig, MavlinkV2FrameParserState } from './MavlinkV2Frame'; +export { FrameFormatConfig, FrameFormatConfigConfig, FrameFormatConfigParserState } from './FrameFormatConfig'; diff --git a/src/struct_frame/frame_parser_py_gen.py b/src/struct_frame/frame_parser_py_gen.py index 5047f21e..3978713a 100644 --- a/src/struct_frame/frame_parser_py_gen.py +++ b/src/struct_frame/frame_parser_py_gen.py @@ -33,7 +33,7 @@ def generate_base(formats): yield '# Automatically generated frame parser base utilities\n' yield f'# Generated by {version} at {time.asctime()}.\n\n' yield 'from enum import Enum\n' - yield 'from typing import List, Tuple, Union\n' + yield 'from typing import Callable, List, Tuple, Union\n' yield 'from dataclasses import dataclass\n\n' # Generate frame format enum @@ -184,33 +184,297 @@ def encode_payload_minimal(output: list, msg_id: int, msg: bytes) -> None: """ output.append(msg_id) output.extend(msg) + + +# ============================================================================= +# Frame Parser Configuration +# ============================================================================= + +@dataclass +class FrameParserConfig: + """ + Configuration interface for frame format parsers. + This allows code reuse through configuration instead of code generation. + """ + name: str + start_bytes: Tuple[int, ...] + header_size: int + footer_size: int + has_length: bool + length_bytes: int + has_crc: bool + + +# ============================================================================= +# Generic Frame Parser +# ============================================================================= +# This class provides a reusable frame parser that can be configured +# for different frame formats, reducing code duplication. + +class GenericParserState(Enum): + """Parser state enumeration""" + LOOKING_FOR_START1 = 0 + LOOKING_FOR_START2 = 1 + GETTING_MSG_ID = 2 + GETTING_LENGTH = 3 + GETTING_PAYLOAD = 4 + + +class GenericFrameParser: + """ + Generic frame parser that works with any frame format configuration. + This class eliminates the need for separate parser classes per format. + """ + + def __init__(self, config: FrameParserConfig, get_msg_length: Callable[[int], int] = None): + self.config = config + self.get_msg_length = get_msg_length + self.reset() + + def _get_initial_state(self) -> GenericParserState: + if len(self.config.start_bytes) == 0: + return GenericParserState.GETTING_MSG_ID + else: + return GenericParserState.LOOKING_FOR_START1 + + def reset(self): + """Reset parser state""" + self.state = self._get_initial_state() + self.buffer = [] + self.packet_size = 0 + self.msg_id = 0 + self.msg_length = 0 + self.length_lo = 0 + + def parse_byte(self, byte: int) -> FrameMsgInfo: + """ + Parse a single byte + + Returns: + FrameMsgInfo with valid=True when a complete valid message is received + """ + result = FrameMsgInfo() + start_bytes = self.config.start_bytes + overhead = self.config.header_size + self.config.footer_size + + if self.state == GenericParserState.LOOKING_FOR_START1: + if byte == start_bytes[0]: + self.buffer = [byte] + if len(start_bytes) > 1: + self.state = GenericParserState.LOOKING_FOR_START2 + else: + self.state = GenericParserState.GETTING_MSG_ID + + elif self.state == GenericParserState.LOOKING_FOR_START2: + if byte == start_bytes[1]: + self.buffer.append(byte) + self.state = GenericParserState.GETTING_MSG_ID + elif byte == start_bytes[0]: + self.buffer = [byte] + # Stay in LOOKING_FOR_START2 + else: + self.state = GenericParserState.LOOKING_FOR_START1 + + elif self.state == GenericParserState.GETTING_MSG_ID: + self.buffer.append(byte) + self.msg_id = byte + if self.config.has_length: + self.state = GenericParserState.GETTING_LENGTH + elif self.get_msg_length: + msg_len = self.get_msg_length(byte) + if msg_len is not None: + self.packet_size = overhead + msg_len + self.state = GenericParserState.GETTING_PAYLOAD + else: + self.state = self._get_initial_state() + else: + self.state = self._get_initial_state() + + elif self.state == GenericParserState.GETTING_LENGTH: + self.buffer.append(byte) + if self.config.length_bytes == 1: + self.msg_length = byte + self.packet_size = overhead + self.msg_length + self.state = GenericParserState.GETTING_PAYLOAD + else: + # 2-byte length + if len(self.buffer) == len(start_bytes) + 2: + self.length_lo = byte + else: + self.msg_length = self.length_lo | (byte << 8) + self.packet_size = overhead + self.msg_length + self.state = GenericParserState.GETTING_PAYLOAD + + elif self.state == GenericParserState.GETTING_PAYLOAD: + self.buffer.append(byte) + if len(self.buffer) >= self.packet_size: + if self.config.has_crc: + result = validate_payload_with_crc( + self.buffer, self.config.header_size, + self.config.length_bytes, len(start_bytes)) + else: + result = validate_payload_minimal(self.buffer, self.config.header_size) + self.state = self._get_initial_state() + + return result + + def encode(self, msg_id: int, msg: bytes) -> bytes: + """ + Encode a message using this format + + Args: + msg_id: Message ID + msg: Message data bytes + + Returns: + Encoded frame as bytes + """ + output = list(self.config.start_bytes) + + if self.config.has_crc: + encode_payload_with_crc(output, msg_id, msg, + self.config.length_bytes, len(self.config.start_bytes)) + else: + encode_payload_minimal(output, msg_id, msg) + + return bytes(output) + + def encode_msg(self, msg) -> bytes: + """Encode a message object (must have msg_id and pack() method)""" + return self.encode(msg.msg_id, msg.pack()) + + @staticmethod + def validate_packet(config: FrameParserConfig, buffer: Union[bytes, List[int]]) -> FrameMsgInfo: + """ + Validate a complete packet in a buffer + + Args: + config: Frame format configuration + buffer: Buffer containing the complete packet + + Returns: + FrameMsgInfo with valid=True if packet is valid + """ + overhead = config.header_size + config.footer_size + + if len(buffer) < overhead: + return FrameMsgInfo() + + # Check start bytes + for i, start_byte in enumerate(config.start_bytes): + if buffer[i] != start_byte: + return FrameMsgInfo() + + # Validate payload + if config.has_crc: + return validate_payload_with_crc(buffer, config.header_size, + config.length_bytes, len(config.start_bytes)) + else: + return validate_payload_minimal(buffer, config.header_size) + + +def create_frame_parser_class(config: FrameParserConfig): + """ + Create a frame parser class for a specific configuration. + This factory function provides pre-configured parser classes. + """ + class ConfiguredFrameParser(GenericFrameParser): + # Class attributes from config + CONFIG = config + START_BYTES = config.start_bytes + HEADER_SIZE = config.header_size + FOOTER_SIZE = config.footer_size + OVERHEAD = config.header_size + config.footer_size + HAS_LENGTH = config.has_length + LENGTH_BYTES = config.length_bytes + HAS_CRC = config.has_crc + + def __init__(self, get_msg_length: Callable[[int], int] = None): + super().__init__(config, get_msg_length) + + @staticmethod + def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: + return GenericFrameParser.validate_packet(config, buffer) + + ConfiguredFrameParser.__name__ = config.name + ConfiguredFrameParser.__qualname__ = config.name + return ConfiguredFrameParser ''' @staticmethod def generate_format_file(fmt): - """Generate a Python file for a single frame format""" + """Generate a Python file for a single frame format using configuration-based approach""" + name = fmt.name + snake_name = camel_to_snake(name) + yield '# Automatically generated frame parser\n' yield f'# Generated by {version} at {time.asctime()}.\n\n' - yield 'from enum import Enum\n' - yield 'from typing import Callable, List, Union\n' yield 'from .frame_base import (\n' - yield ' FrameMsgInfo, fletcher_checksum,\n' - yield ' validate_payload_with_crc, validate_payload_minimal,\n' - yield ' encode_payload_with_crc, encode_payload_minimal,\n' + yield ' FrameParserConfig, create_frame_parser_class, GenericParserState,\n' yield ')\n\n' - yield from FrameParserPyGen.generate_format(fmt) + # Generate configuration object + yield f'# =============================================================================\n' + yield f'# {name} Frame Format Configuration\n' + yield f'# =============================================================================\n\n' + + yield f'# Configuration for {name} frame format\n' + + # Start bytes tuple + start_bytes_str = ', '.join([f'0x{sb[1]:02X}' for sb in fmt.start_bytes]) + if len(fmt.start_bytes) <= 1: + start_bytes_str += ',' # Single element tuple needs trailing comma + + yield f'{name}Config = FrameParserConfig(\n' + yield f' name=\'{name}\',\n' + yield f' start_bytes=({start_bytes_str}),\n' + yield f' header_size={fmt.header_size},\n' + yield f' footer_size={fmt.footer_size},\n' + yield f' has_length={fmt.has_length},\n' + yield f' length_bytes={fmt.length_bytes},\n' + yield f' has_crc={fmt.has_crc},\n' + yield ')\n\n' + + # Generate the class using the factory function + yield f'\"\"\"\n' + yield f'{name} - Frame format parser and encoder\n' + yield f'\n' + yield f'Format: ' + parts = [] + for sb_name, sb_value in fmt.start_bytes: + parts.append(f'[{sb_name.upper()}=0x{sb_value:02X}]') + parts.append('[MSG_ID]') + if fmt.has_length: + parts.append(f'[LEN{"16" if fmt.length_bytes == 2 else ""}]') + parts.append('[MSG...]') + if fmt.has_crc: + parts.append('[CRC1] [CRC2]') + yield ' '.join(parts) + yield '\n\n' + yield f'This class is generated using create_frame_parser_class() for code reuse.\n' + yield f'\"\"\"\n' + yield f'{name} = create_frame_parser_class({name}Config)\n\n' + + # Export parser state alias for backward compatibility + yield f'# Parser state alias for backward compatibility\n' + yield f'{name}ParserState = GenericParserState\n' @staticmethod def generate_init(formats): """Generate __init__.py that exports all frame formats""" yield '# Automatically generated frame parser package\n' yield f'# Generated by {version} at {time.asctime()}.\n\n' - yield '# Base utilities\n' + yield '# Base utilities and generic parser infrastructure\n' yield 'from .frame_base import (\n' yield ' FrameFormatType,\n' yield ' FrameMsgInfo,\n' yield ' fletcher_checksum,\n' + yield ' # Configuration interface for code reuse\n' + yield ' FrameParserConfig,\n' + yield ' # Generic parser class (use create_frame_parser_class for type-safe wrappers)\n' + yield ' GenericFrameParser,\n' + yield ' GenericParserState,\n' + yield ' create_frame_parser_class,\n' yield ' # Shared payload parsing functions\n' yield ' validate_payload_with_crc,\n' yield ' validate_payload_minimal,\n' @@ -218,10 +482,10 @@ def generate_init(formats): yield ' encode_payload_minimal,\n' yield ')\n\n' - yield '# Individual frame format parsers\n' + yield '# Individual frame format parsers (configuration-based)\n' for fmt in formats: snake_name = camel_to_snake(fmt.name) - yield f'from .{snake_name} import {fmt.name}, {fmt.name}ParserState\n' + yield f'from .{snake_name} import {fmt.name}, {fmt.name}Config, {fmt.name}ParserState\n' yield '\n# Re-export all frame formats\n' yield '__all__ = [\n' @@ -229,6 +493,11 @@ def generate_init(formats): yield ' "FrameFormatType",\n' yield ' "FrameMsgInfo",\n' yield ' "fletcher_checksum",\n' + yield ' # Configuration and generic parser\n' + yield ' "FrameParserConfig",\n' + yield ' "GenericFrameParser",\n' + yield ' "GenericParserState",\n' + yield ' "create_frame_parser_class",\n' yield ' # Shared payload parsing functions\n' yield ' "validate_payload_with_crc",\n' yield ' "validate_payload_minimal",\n' @@ -237,6 +506,7 @@ def generate_init(formats): yield ' # Frame formats\n' for fmt in formats: yield f' "{fmt.name}",\n' + yield f' "{fmt.name}Config",\n' yield f' "{fmt.name}ParserState",\n' yield ']\n' diff --git a/src/struct_frame/frame_parser_ts_gen.py b/src/struct_frame/frame_parser_ts_gen.py index cdf8fff3..3789e935 100644 --- a/src/struct_frame/frame_parser_ts_gen.py +++ b/src/struct_frame/frame_parser_ts_gen.py @@ -29,7 +29,7 @@ class FrameParserTsGen: @staticmethod def generate_base(formats): - """Generate the base TypeScript file with common utilities""" + """Generate the base TypeScript file with common utilities and generic parser""" yield '// Automatically generated frame parser base utilities\n' yield f'// Generated by {version} at {time.asctime()}.\n\n' @@ -80,6 +80,31 @@ def generate_base(formats): }; } +// ============================================================================= +// Frame Format Configuration +// ============================================================================= + +/** + * Configuration interface for frame format parsers. + * This allows code reuse through configuration instead of code generation. + */ +export interface FrameParserConfig { + /** Name of the frame format (e.g., 'BasicDefault', 'TinyMinimal') */ + readonly name: string; + /** Start byte values (0, 1, or 2 bytes) */ + readonly startBytes: readonly number[]; + /** Total header size in bytes */ + readonly headerSize: number; + /** Total footer size in bytes (usually 0 or 2 for CRC) */ + readonly footerSize: number; + /** Whether this format includes a length field */ + readonly hasLength: boolean; + /** Number of bytes for length field (1 or 2) */ + readonly lengthBytes: number; + /** Whether this format includes CRC */ + readonly hasCrc: boolean; +} + // ============================================================================= // Shared Payload Parsing Functions // ============================================================================= @@ -186,32 +211,310 @@ def generate_base(formats): output.push(msg[i]); } } + +// ============================================================================= +// Generic Frame Parser +// ============================================================================= +// This class provides a reusable frame parser that can be configured +// for different frame formats, reducing code duplication. + +/** Parser state enumeration */ +export enum GenericParserState { + LOOKING_FOR_START1 = 0, + LOOKING_FOR_START2 = 1, + GETTING_MSG_ID = 2, + GETTING_LENGTH = 3, + GETTING_PAYLOAD = 4 +} + +/** + * Generic frame parser that works with any frame format configuration. + * This class eliminates the need for separate parser classes per format. + */ +export class GenericFrameParser { + readonly config: FrameParserConfig; + + private state: GenericParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private msg_length: number; + private length_lo: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + constructor(config: FrameParserConfig, get_msg_length?: (msg_id: number) => number | undefined) { + this.config = config; + this.get_msg_length = get_msg_length; + this.state = this.getInitialState(); + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + private getInitialState(): GenericParserState { + if (this.config.startBytes.length === 0) { + return GenericParserState.GETTING_MSG_ID; + } else if (this.config.startBytes.length === 1) { + return GenericParserState.LOOKING_FOR_START1; + } else { + return GenericParserState.LOOKING_FOR_START1; + } + } + + reset(): void { + this.state = this.getInitialState(); + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + const startBytes = this.config.startBytes; + const overhead = this.config.headerSize + this.config.footerSize; + + switch (this.state) { + case GenericParserState.LOOKING_FOR_START1: + if (byte === startBytes[0]) { + this.buffer = [byte]; + if (startBytes.length > 1) { + this.state = GenericParserState.LOOKING_FOR_START2; + } else { + this.state = GenericParserState.GETTING_MSG_ID; + } + } + break; + + case GenericParserState.LOOKING_FOR_START2: + if (byte === startBytes[1]) { + this.buffer.push(byte); + this.state = GenericParserState.GETTING_MSG_ID; + } else if (byte === startBytes[0]) { + this.buffer = [byte]; + // Stay in LOOKING_FOR_START2 + } else { + this.state = GenericParserState.LOOKING_FOR_START1; + } + break; + + case GenericParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + if (this.config.hasLength) { + this.state = GenericParserState.GETTING_LENGTH; + } else if (this.get_msg_length) { + const msgLen = this.get_msg_length(byte); + if (msgLen !== undefined) { + this.packet_size = overhead + msgLen; + this.state = GenericParserState.GETTING_PAYLOAD; + } else { + this.state = this.getInitialState(); + } + } else { + this.state = this.getInitialState(); + } + break; + + case GenericParserState.GETTING_LENGTH: + this.buffer.push(byte); + if (this.config.lengthBytes === 1) { + this.msg_length = byte; + this.packet_size = overhead + this.msg_length; + this.state = GenericParserState.GETTING_PAYLOAD; + } else { + // 2-byte length + if (this.buffer.length === startBytes.length + 2) { + this.length_lo = byte; + } else { + this.msg_length = this.length_lo | (byte << 8); + this.packet_size = overhead + this.msg_length; + this.state = GenericParserState.GETTING_PAYLOAD; + } + } + break; + + case GenericParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + if (this.buffer.length >= this.packet_size) { + if (this.config.hasCrc) { + const validationResult = validate_payload_with_crc( + this.buffer, this.config.headerSize, this.config.lengthBytes, startBytes.length); + if (validationResult.valid) { + result.valid = validationResult.valid; + result.msg_id = validationResult.msg_id; + result.msg_len = validationResult.msg_len; + result.msg_data = validationResult.msg_data; + } + } else { + const validationResult = validate_payload_minimal(this.buffer, this.config.headerSize); + result.valid = validationResult.valid; + result.msg_id = validationResult.msg_id; + result.msg_len = validationResult.msg_len; + result.msg_data = validationResult.msg_data; + } + this.state = this.getInitialState(); + } + break; + } + + return result; + } + + /** + * Encode a message using this format + */ + static encode(config: FrameParserConfig, msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + + // Add start bytes + for (const startByte of config.startBytes) { + output.push(startByte); + } + + // Use appropriate payload encoding + if (config.hasCrc) { + encode_payload_with_crc(output, msg_id, msg, config.lengthBytes, config.startBytes.length); + } else { + encode_payload_minimal(output, msg_id, msg); + } + + return new Uint8Array(output); + } + + /** + * Validate a complete packet buffer using this format + */ + static validate_packet(config: FrameParserConfig, buffer: Uint8Array | number[]): FrameMsgInfo { + const overhead = config.headerSize + config.footerSize; + + if (buffer.length < overhead) { + return createFrameMsgInfo(); + } + + // Check start bytes + for (let i = 0; i < config.startBytes.length; i++) { + if (buffer[i] !== config.startBytes[i]) { + return createFrameMsgInfo(); + } + } + + // Validate payload + if (config.hasCrc) { + return validate_payload_with_crc(buffer, config.headerSize, config.lengthBytes, config.startBytes.length); + } else { + return validate_payload_minimal(buffer, config.headerSize); + } + } +} + +/** + * Create a typed frame parser class for a specific configuration. + * This factory function provides type-safe wrappers around GenericFrameParser. + */ +export function createFrameParserClass(config: FrameParserConfig) { + return class extends GenericFrameParser { + // Static properties from config + static readonly START_BYTES = config.startBytes; + static readonly HEADER_SIZE = config.headerSize; + static readonly FOOTER_SIZE = config.footerSize; + static readonly OVERHEAD = config.headerSize + config.footerSize; + static readonly HAS_LENGTH = config.hasLength; + static readonly LENGTH_BYTES = config.lengthBytes; + static readonly HAS_CRC = config.hasCrc; + static readonly CONFIG = config; + + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + super(config, get_msg_length); + } + + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + return GenericFrameParser.encode(config, msg_id, msg); + } + + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + return GenericFrameParser.validate_packet(config, buffer); + } + }; +} ''' @staticmethod def generate_format_file(fmt): - """Generate a TypeScript file for a single frame format""" + """Generate a TypeScript file for a single frame format using configuration-based approach""" + name = fmt.name + yield '// Automatically generated frame parser\n' yield f'// Generated by {version} at {time.asctime()}.\n\n' yield 'import {\n' - yield ' FrameMsgInfo, createFrameMsgInfo, fletcher_checksum,\n' - yield ' validate_payload_with_crc, validate_payload_minimal,\n' - yield ' encode_payload_with_crc, encode_payload_minimal,\n' + yield ' FrameParserConfig, createFrameParserClass, GenericParserState,\n' yield '} from \'./frame_base\';\n\n' - yield from FrameParserTsGen.generate_format(fmt) + # Generate configuration object + yield f'// =============================================================================\n' + yield f'// {name} Frame Format Configuration\n' + yield f'// =============================================================================\n\n' + + yield f'/** Configuration for {name} frame format */\n' + yield f'export const {name}Config: FrameParserConfig = {{\n' + yield f' name: \'{name}\',\n' + + # Start bytes array + start_bytes_str = ', '.join([f'0x{sb[1]:02X}' for sb in fmt.start_bytes]) + yield f' startBytes: [{start_bytes_str}],\n' + + yield f' headerSize: {fmt.header_size},\n' + yield f' footerSize: {fmt.footer_size},\n' + yield f' hasLength: {str(fmt.has_length).lower()},\n' + yield f' lengthBytes: {fmt.length_bytes},\n' + yield f' hasCrc: {str(fmt.has_crc).lower()},\n' + yield '};\n\n' + + # Generate the class using the factory function + yield f'/**\n' + yield f' * {name} - Frame format parser and encoder\n' + yield f' * \n' + yield f' * Format: ' + parts = [] + for sb_name, sb_value in fmt.start_bytes: + parts.append(f'[{sb_name.upper()}=0x{sb_value:02X}]') + parts.append('[MSG_ID]') + if fmt.has_length: + parts.append(f'[LEN{"16" if fmt.length_bytes == 2 else ""}]') + parts.append('[MSG...]') + if fmt.has_crc: + parts.append('[CRC1] [CRC2]') + yield ' '.join(parts) + yield '\n *\n' + yield f' * This class is generated using createFrameParserClass() for code reuse.\n' + yield f' */\n' + yield f'export const {name} = createFrameParserClass({name}Config);\n\n' + + # Export parser state type alias for backward compatibility + yield f'/** Parser state type alias for backward compatibility */\n' + yield f'export type {name}ParserState = GenericParserState;\n' + yield f'export {{ GenericParserState as {name}ParserState_Enum }};\n' @staticmethod def generate_index(formats): """Generate index.ts that exports all frame formats""" yield '// Automatically generated frame parser package\n' yield f'// Generated by {version} at {time.asctime()}.\n\n' - yield '// Base utilities\n' + yield '// Base utilities and generic parser infrastructure\n' yield 'export {\n' yield ' FrameFormatType,\n' yield ' FrameMsgInfo,\n' yield ' createFrameMsgInfo,\n' yield ' fletcher_checksum,\n' + yield ' // Configuration interface for code reuse\n' + yield ' FrameParserConfig,\n' + yield ' // Generic parser class (use createFrameParserClass for type-safe wrappers)\n' + yield ' GenericFrameParser,\n' + yield ' GenericParserState,\n' + yield ' createFrameParserClass,\n' yield ' // Shared payload parsing functions\n' yield ' validate_payload_with_crc,\n' yield ' validate_payload_minimal,\n' @@ -219,9 +522,9 @@ def generate_index(formats): yield ' encode_payload_minimal,\n' yield '} from \'./frame_base\';\n\n' - yield '// Individual frame format parsers\n' + yield '// Individual frame format parsers (configuration-based)\n' for fmt in formats: - yield f'export {{ {fmt.name}, {fmt.name}ParserState }} from \'./{fmt.name}\';\n' + yield f'export {{ {fmt.name}, {fmt.name}Config, {fmt.name}ParserState }} from \'./{fmt.name}\';\n' @staticmethod def generate(formats): @@ -703,7 +1006,7 @@ class FrameParserJsGen: @staticmethod def generate_base(formats): - """Generate the base JavaScript file with common utilities""" + """Generate the base JavaScript file with common utilities and generic parser""" yield '// Automatically generated frame parser base utilities\n' yield f'// Generated by {version} at {time.asctime()}.\n\n' @@ -715,7 +1018,7 @@ def generate_base(formats): yield f' {enum_name}: {i},\n' yield '};\n\n' - # Generate checksum function + # Generate checksum function and utilities yield '''// Fletcher-16 checksum calculation function fletcher_checksum(buffer, start = 0, end = undefined) { if (end === undefined) { @@ -832,6 +1135,226 @@ def generate_base(formats): } } +// ============================================================================= +// Generic Frame Parser +// ============================================================================= +// This class provides a reusable frame parser that can be configured +// for different frame formats, reducing code duplication. + +/** Parser state enumeration */ +const GenericParserState = { + LOOKING_FOR_START1: 0, + LOOKING_FOR_START2: 1, + GETTING_MSG_ID: 2, + GETTING_LENGTH: 3, + GETTING_PAYLOAD: 4 +}; + +/** + * Generic frame parser that works with any frame format configuration. + * This class eliminates the need for separate parser classes per format. + */ +class GenericFrameParser { + constructor(config, get_msg_length = undefined) { + this.config = config; + this.get_msg_length = get_msg_length; + this.state = this._getInitialState(); + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + _getInitialState() { + if (this.config.startBytes.length === 0) { + return GenericParserState.GETTING_MSG_ID; + } else { + return GenericParserState.LOOKING_FOR_START1; + } + } + + reset() { + this.state = this._getInitialState(); + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + const startBytes = this.config.startBytes; + const overhead = this.config.headerSize + this.config.footerSize; + + switch (this.state) { + case GenericParserState.LOOKING_FOR_START1: + if (byte === startBytes[0]) { + this.buffer = [byte]; + if (startBytes.length > 1) { + this.state = GenericParserState.LOOKING_FOR_START2; + } else { + this.state = GenericParserState.GETTING_MSG_ID; + } + } + break; + + case GenericParserState.LOOKING_FOR_START2: + if (byte === startBytes[1]) { + this.buffer.push(byte); + this.state = GenericParserState.GETTING_MSG_ID; + } else if (byte === startBytes[0]) { + this.buffer = [byte]; + // Stay in LOOKING_FOR_START2 + } else { + this.state = GenericParserState.LOOKING_FOR_START1; + } + break; + + case GenericParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + if (this.config.hasLength) { + this.state = GenericParserState.GETTING_LENGTH; + } else if (this.get_msg_length) { + const msgLen = this.get_msg_length(byte); + if (msgLen !== undefined) { + this.packet_size = overhead + msgLen; + this.state = GenericParserState.GETTING_PAYLOAD; + } else { + this.state = this._getInitialState(); + } + } else { + this.state = this._getInitialState(); + } + break; + + case GenericParserState.GETTING_LENGTH: + this.buffer.push(byte); + if (this.config.lengthBytes === 1) { + this.msg_length = byte; + this.packet_size = overhead + this.msg_length; + this.state = GenericParserState.GETTING_PAYLOAD; + } else { + // 2-byte length + if (this.buffer.length === startBytes.length + 2) { + this.length_lo = byte; + } else { + this.msg_length = this.length_lo | (byte << 8); + this.packet_size = overhead + this.msg_length; + this.state = GenericParserState.GETTING_PAYLOAD; + } + } + break; + + case GenericParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + if (this.buffer.length >= this.packet_size) { + if (this.config.hasCrc) { + const validationResult = validate_payload_with_crc( + this.buffer, this.config.headerSize, this.config.lengthBytes, startBytes.length); + if (validationResult.valid) { + result.valid = validationResult.valid; + result.msg_id = validationResult.msg_id; + result.msg_len = validationResult.msg_len; + result.msg_data = validationResult.msg_data; + } + } else { + const validationResult = validate_payload_minimal(this.buffer, this.config.headerSize); + result.valid = validationResult.valid; + result.msg_id = validationResult.msg_id; + result.msg_len = validationResult.msg_len; + result.msg_data = validationResult.msg_data; + } + this.state = this._getInitialState(); + } + break; + } + + return result; + } + + /** + * Encode a message using this format (static method) + */ + static encode(config, msg_id, msg) { + const output = []; + + // Add start bytes + for (const startByte of config.startBytes) { + output.push(startByte); + } + + // Use appropriate payload encoding + if (config.hasCrc) { + encode_payload_with_crc(output, msg_id, msg, config.lengthBytes, config.startBytes.length); + } else { + encode_payload_minimal(output, msg_id, msg); + } + + return new Uint8Array(output); + } + + /** + * Validate a complete packet buffer using this format (static method) + */ + static validate_packet(config, buffer) { + const overhead = config.headerSize + config.footerSize; + + if (buffer.length < overhead) { + return createFrameMsgInfo(); + } + + // Check start bytes + for (let i = 0; i < config.startBytes.length; i++) { + if (buffer[i] !== config.startBytes[i]) { + return createFrameMsgInfo(); + } + } + + // Validate payload + if (config.hasCrc) { + return validate_payload_with_crc(buffer, config.headerSize, config.lengthBytes, config.startBytes.length); + } else { + return validate_payload_minimal(buffer, config.headerSize); + } + } +} + +/** + * Create a frame parser class for a specific configuration. + * This factory function provides pre-configured parser classes. + */ +function createFrameParserClass(config) { + // Create a class that extends GenericFrameParser with the config baked in + class ConfiguredFrameParser extends GenericFrameParser { + constructor(get_msg_length = undefined) { + super(config, get_msg_length); + } + + static encode(msg_id, msg) { + return GenericFrameParser.encode(config, msg_id, msg); + } + + static validate_packet(buffer) { + return GenericFrameParser.validate_packet(config, buffer); + } + } + + // Add static properties from config + ConfiguredFrameParser.START_BYTES = config.startBytes; + ConfiguredFrameParser.HEADER_SIZE = config.headerSize; + ConfiguredFrameParser.FOOTER_SIZE = config.footerSize; + ConfiguredFrameParser.OVERHEAD = config.headerSize + config.footerSize; + ConfiguredFrameParser.HAS_LENGTH = config.hasLength; + ConfiguredFrameParser.LENGTH_BYTES = config.lengthBytes; + ConfiguredFrameParser.HAS_CRC = config.hasCrc; + ConfiguredFrameParser.CONFIG = config; + + return ConfiguredFrameParser; +} + module.exports = { FrameFormatType, fletcher_checksum, @@ -840,25 +1363,71 @@ def generate_base(formats): validate_payload_minimal, encode_payload_with_crc, encode_payload_minimal, + GenericParserState, + GenericFrameParser, + createFrameParserClass, }; ''' @staticmethod def generate_format_file(fmt): - """Generate a JavaScript file for a single frame format""" + """Generate a JavaScript file for a single frame format using configuration-based approach""" + name = fmt.name + yield '// Automatically generated frame parser\n' yield f'// Generated by {version} at {time.asctime()}.\n\n' yield 'const {\n' - yield ' createFrameMsgInfo, fletcher_checksum,\n' - yield ' validate_payload_with_crc, validate_payload_minimal,\n' - yield ' encode_payload_with_crc, encode_payload_minimal,\n' + yield ' createFrameParserClass, GenericParserState,\n' yield '} = require(\'./frame_base\');\n\n' - yield from FrameParserJsGen.generate_format(fmt) - - yield '\nmodule.exports = {\n' - yield f' {fmt.name},\n' - yield f' {fmt.name}ParserState,\n' + # Generate configuration object + yield f'// =============================================================================\n' + yield f'// {name} Frame Format Configuration\n' + yield f'// =============================================================================\n\n' + + yield f'/** Configuration for {name} frame format */\n' + yield f'const {name}Config = {{\n' + yield f' name: \'{name}\',\n' + + # Start bytes array + start_bytes_str = ', '.join([f'0x{sb[1]:02X}' for sb in fmt.start_bytes]) + yield f' startBytes: [{start_bytes_str}],\n' + + yield f' headerSize: {fmt.header_size},\n' + yield f' footerSize: {fmt.footer_size},\n' + yield f' hasLength: {str(fmt.has_length).lower()},\n' + yield f' lengthBytes: {fmt.length_bytes},\n' + yield f' hasCrc: {str(fmt.has_crc).lower()},\n' + yield '};\n\n' + + # Generate the class using the factory function + yield f'/**\n' + yield f' * {name} - Frame format parser and encoder\n' + yield f' * \n' + yield f' * Format: ' + parts = [] + for sb_name, sb_value in fmt.start_bytes: + parts.append(f'[{sb_name.upper()}=0x{sb_value:02X}]') + parts.append('[MSG_ID]') + if fmt.has_length: + parts.append(f'[LEN{"16" if fmt.length_bytes == 2 else ""}]') + parts.append('[MSG...]') + if fmt.has_crc: + parts.append('[CRC1] [CRC2]') + yield ' '.join(parts) + yield '\n *\n' + yield f' * This class is generated using createFrameParserClass() for code reuse.\n' + yield f' */\n' + yield f'const {name} = createFrameParserClass({name}Config);\n\n' + + # Export parser state alias for backward compatibility + yield f'/** Parser state alias for backward compatibility */\n' + yield f'const {name}ParserState = GenericParserState;\n\n' + + yield 'module.exports = {\n' + yield f' {name},\n' + yield f' {name}Config,\n' + yield f' {name}ParserState,\n' yield '};\n' @staticmethod