Workflow VS Code / Copilot pour générer des structures de messages C++ au style maison à partir d'un PDF de spécification (ICD, protocole binaire de marché, etc.).
Pour chaque message, le workflow produit :
#pragma pack(push, 1)
struct PostTradeStruct
{
uint8 m_MDUpdateAction;
int64 m_MsgSeqNum;
char m_SecurityID[12];
Decimal m_MDEntryPx;
// ...
};
#pragma pack(pop)
class PostTrade
{
MessageHeader const m_MessageHeader;
PostTradeStruct const & m_Struct;
public:
static constexpr const uint16 TYPE = 201;
static constexpr const char* NAME = "PostTrade";
static const unsigned int SIZE = MessageHeader::SIZE + sizeof(PostTradeStruct);
explicit PostTrade(InputData const & data)
: m_MessageHeader(data)
, m_Struct(*reinterpret_cast<const PostTradeStruct*>(data.data() + MessageHeader::SIZE))
{}
uint8 getMDUpdateAction() const { return m_Struct.m_MDUpdateAction; }
int64 getMsgSeqNum() const { return m_Struct.m_MsgSeqNum; }
std::string getSecurityID() const { return std::string(m_Struct.m_SecurityID, 12); }
Decimal getMDEntryPx() const { return m_Struct.m_MDEntryPx; }
// ...
virtual void dump(std::ostream & os) const
{
m_MessageHeader.dump(os);
os
DUMP_FIELD_AS_INT(MDUpdateAction)
DUMP_FIELD(MsgSeqNum)
DUMP_FIELD(SecurityID)
DUMP_FIELD(MDEntryPx)
;
}
};
inline std::ostream& operator<<(std::ostream& out, const PostTrade& obj)
{ obj.dump(out); return out; }Caractéristiques imposées (voir .github/instructions/cpp-messages.instructions.md) :
- typedefs courts :
uint8,int16,int64,Decimal,TimestampNano— pas destd::uint*_t, - préfixe
m_PascalCase sur tous les champs, <Name>Structpour la struct binaire packée,<Name>pour la classe wrapper,- accès au binaire via
reinterpret_cast+ référenceconst &(zéro copie), - getters :
std::stringpourchar[N], type direct sinon, dump()avec macrosDUMP_FIELD/DUMP_FIELD_AS_INT,operator<<inline.
.github/
prompts/
pdf-to-cpp-messages.prompt.md # Prompt — extraction des messages
pdf-to-cpp-types.prompt.md # Prompt — extraction d'un type réutilisable (par §/Table)
instructions/
cpp-messages.instructions.md # Conventions C++ auto-appliquées aux .hpp/.cpp
templates/
Message.hpp.template # Template message paramétré
Type.hpp.template # Template type paramétré (struct/enum/bitfield/alias)
include/
messages/
Common.hpp # Typedefs uint8/int64/..., Decimal, TimestampNano, InputData, DUMP_FIELD
MessageHeader.hpp # STUB — à remplacer selon la spec utilisateur
PacketHeader.hpp # STUB — à remplacer si protocole avec framing paquet
MessageIds.hpp # Registre central des opcodes
types/
Types.hpp # Header agrégateur des types
GeoPosition.hpp # Exemple de type généré
examples/
PostTrade.hpp # Exemple de sortie attendue (style maison complet)
specs/ # (à créer) — vos PDF de spec
Le workflow demande systématiquement avant de générer le moindre message :
- Quel est le layout du
MessageHeader(champs, taille, méthodedump()) ? - Existe-t-il un
PacketHeader(framing paquet de transport) ? Si oui, son layout. - Les types domaine (
Decimal,TimestampNano,InputData) correspondent-ils déjà au projet, ou faut-il les adapter dans include/messages/Common.hpp ?
Réponds à ces questions avant de continuer — sinon les stubs include/messages/MessageHeader.hpp et include/messages/PacketHeader.hpp seront utilisés tels quels (et marqués TODO).
Place ton PDF de spécification dans specs/ (ex: specs/protocol_v1.pdf).
Si Copilot ne peut pas lire le PDF directement, extrais le texte au préalable :
pdftotext -layout specs/protocol_v1.pdf specs/protocol_v1.txt
Si la spec définit des types partagés (struct composé, enum, bitfield) dans des paragraphes / tables dédiés, génère-les avant les messages :
/pdf-to-cpp-types
Copilot va te demander :
- le PDF,
- la section / table précise (ex:
§4.3.2,Table 7), - le nom du type (ex:
GeoPosition), - la catégorie (
struct/enum/bitfield/alias).
Le type est créé dans include/messages/types/<Nom>.hpp et ajouté à Types.hpp.
/pdf-to-cpp-messages
Copilot va :
- Demander le layout de
MessageHeaderetPacketHeader(étape 0). - Lister les messages détectés → demander confirmation.
- Générer un
.hpppar message (struct + classe wrapper + dump + operator<<). - Mettre à jour include/messages/MessageIds.hpp.
- Signaler les champs ambigus (
// TODO:).
# Linux / WSL / MinGW
g++ -std=c++17 -Wall -Wextra -Iinclude -c examples/PostTrade.hpp -o NUL
# MSVC
cl /std:c++17 /W4 /Iinclude /c examples/PostTrade.hppLes static_assert échoueront à la compilation si la taille ne correspond pas à la spec.
- .github/instructions/cpp-messages.instructions.md — règles de codage.
- include/messages/Common.hpp — adapte
Decimal,TimestampNano,InputDataaux types réels du projet. - include/messages/MessageHeader.hpp — remplace le stub par le vrai
MessageHeader. - include/messages/PacketHeader.hpp — idem ou supprimer si non applicable.
- VS Code 1.96+
- Extension GitHub Copilot Chat activée
- Modèle Claude (Sonnet/Opus) recommandé pour l'analyse PDF longue
- Compilateur C++17 minimum