Konstrukcja (biblioteka Pythona)
Construct to biblioteka Pythona do konstrukcji i dekonstrukcji struktur danych w sposób deklaratywny . W tym kontekście konstrukcja lub budowa odnosi się do procesu konwersji ( serializacji ) obiektu programistycznego na reprezentację binarną. Dekonstrukcja lub parsowanie odnosi się do przeciwnego procesu konwersji (deserializacji) danych binarnych na obiekt programistyczny. Bycie deklaratywnym oznacza, że kod użytkownika definiuje strukturę danych, zamiast konwencji pisania kodu proceduralnego w celu osiągnięcia celu. Construct może bezproblemowo pracować z szczegółowością danych na poziomie bitów i bajtów oraz różnymi porządkowaniami bajtów .
Używanie kodu deklaratywnego ma wiele zalet. Na przykład ten sam kod, który można analizować, można również budować (symetryczny), debugowanie i testowanie jest znacznie prostsze (do pewnego stopnia możliwe do udowodnienia), tworzenie nowych konstrukcji jest łatwe (zawijanie komponentów) i wiele innych. Jeśli ktoś jest zaznajomiony z C (językiem programowania) , może myśleć o konstrukcjach jako rzutowaniu z char *
na struct foo *
i odwrotnie, zamiast pisania kodu, który rozpakowuje dane.
Przykład
Poniższy przykład pokazuje, jak można zdefiniować stos protokołów TCP/IP przy użyciu konstrukcji. Część kodu została pominięta ze względu na zwięzłość i prostotę. Zauważ też, że poniższy kod to tylko kod Pythona, który tworzy obiekty.
Najpierw nagłówek Ethernet (warstwa 2):
ethernet = Struct ( „miejsce docelowe” / Bajty ( 6 ), „źródło” / Bajty ( 6 ), „typ” / Enum ( Int16ub , IPv4 = 0x0800 , ARP = 0x0806 , RARP = 0x8035 , X25 = 0x0805 , IPX = 0x8137 , IPv6 = 0x86DD , ), )
Następnie nagłówek IP (warstwa 3):
ip = Struct ( "header" / BitStruct ( "version" / Const ( Nibble , 4 ), "header_length" / Nibble , ), "tos" / BitStruct ( "precedence" / Bytes ( 3 ), "minimalizuj_opóźnienie" / Flaga , "high_throuput" / Flaga , "high_reliability" / Flaga , "minimize_cost" / Flaga , Padding ( 1 ), ), "całkowita_długość" / Int16ub , # ... )
I wreszcie nagłówek TCP (warstwa 4):
tcp = Struct ( "źródło" / Int16ub , "miejsce docelowe" / Int16ub , "seq" / Int32ub , "ack" / Int32ub , # ... )
Teraz zdefiniuj hierarchię stosu protokołów. Poniższy kod „wiąże” każdą parę sąsiednich protokołów w oddzielną jednostkę. Każda taka jednostka „wybierze” odpowiednią następną warstwę na podstawie zawartego w niej protokołu.
layer4tcp = Struct ( tcp , # ... payload ) layer3ip = Struct ( ip , "next" / Switch ( this . protocol , { "TCP" : layer4tcp , } ), ) layer2ethernet = Struct ( ethernet , "next" / Switch ( ten . typ , { "IP" : layer3ip , } ), )
W tym momencie kod może analizować przechwycone ramki TCP/IP w obiekty „pakietowe” i budować te obiekty pakietowe z powrotem w postaci binarnej.
tcpip_stack = pakiet Layer2Ethernet = tcpip_stack . parse ( b "...surowy przechwycony pakiet..." ) raw_data = tcpip_stack . kompilacja ( pakiet )
Porty i spin-offy
Perl
Data::ParseBinary to moduł CPAN , który powstał jako port Construct do języka programowania Perl . (zobacz jego główny dokument POD, aby znaleźć inspirację). Od pierwszej wersji niektóre części oryginalnego interfejsu API zostały wycofane.
Jawa
Port do Javy jest dostępny na GitHub . Przykłady w Javie, Ethernet (warstwa 2):
Construct ethernet_header = Struct ( "ethernet_header" , MacAddress ( "miejsce docelowe" ), MacAddress ( "źródło" ), Enum ( UBInt16 ( "typ" ), "IPv4" , 0x0800 , "ARP" , 0x0806 , "RARP" , 0x8035 , "X25" , 0x0805 , "IPX" , 0x8137 , "IPv6" , 0x86DD , "_default_" , pass ));