polyfile-weave 0.5.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of polyfile-weave might be problematic. Click here for more details.
- polyfile/__init__.py +15 -0
- polyfile/__main__.py +394 -0
- polyfile/arithmetic.py +27 -0
- polyfile/ast.py +114 -0
- polyfile/debugger.py +1039 -0
- polyfile/expressions.py +346 -0
- polyfile/fileutils.py +343 -0
- polyfile/html.py +135 -0
- polyfile/http/__init__.py +1 -0
- polyfile/http/defacto.py +37 -0
- polyfile/http/deprecated.py +51 -0
- polyfile/http/experimental.py +67 -0
- polyfile/http/http_11.py +548 -0
- polyfile/http/matcher.py +37 -0
- polyfile/http/structured_headers.py +48 -0
- polyfile/iterators.py +72 -0
- polyfile/jpeg.py +24 -0
- polyfile/kaitai/__init__.py +0 -0
- polyfile/kaitai/compiler.py +156 -0
- polyfile/kaitai/parser.py +312 -0
- polyfile/kaitai/parsers/__init__.py +0 -0
- polyfile/kaitai/parsers/aix_utmp.py +116 -0
- polyfile/kaitai/parsers/allegro_dat.py +367 -0
- polyfile/kaitai/parsers/andes_firmware.py +64 -0
- polyfile/kaitai/parsers/android_bootldr_asus.py +105 -0
- polyfile/kaitai/parsers/android_bootldr_huawei.py +181 -0
- polyfile/kaitai/parsers/android_bootldr_qcom.py +217 -0
- polyfile/kaitai/parsers/android_dto.py +138 -0
- polyfile/kaitai/parsers/android_img.py +319 -0
- polyfile/kaitai/parsers/android_nanoapp_header.py +83 -0
- polyfile/kaitai/parsers/android_opengl_shaders_cache.py +151 -0
- polyfile/kaitai/parsers/android_sparse.py +237 -0
- polyfile/kaitai/parsers/android_super.py +401 -0
- polyfile/kaitai/parsers/apm_partition_table.py +196 -0
- polyfile/kaitai/parsers/apple_single_double.py +180 -0
- polyfile/kaitai/parsers/asn1_der.py +235 -0
- polyfile/kaitai/parsers/au.py +138 -0
- polyfile/kaitai/parsers/avantes_roh60.py +112 -0
- polyfile/kaitai/parsers/avi.py +296 -0
- polyfile/kaitai/parsers/bcd.py +111 -0
- polyfile/kaitai/parsers/bitcoin_transaction.py +210 -0
- polyfile/kaitai/parsers/blender_blend.py +334 -0
- polyfile/kaitai/parsers/bmp.py +780 -0
- polyfile/kaitai/parsers/bson.py +411 -0
- polyfile/kaitai/parsers/btrfs_stream.py +318 -0
- polyfile/kaitai/parsers/bytes_with_io.py +27 -0
- polyfile/kaitai/parsers/chrome_pak.py +194 -0
- polyfile/kaitai/parsers/code_6502.py +456 -0
- polyfile/kaitai/parsers/compressed_resource.py +217 -0
- polyfile/kaitai/parsers/cpio_old_le.py +154 -0
- polyfile/kaitai/parsers/cramfs.py +344 -0
- polyfile/kaitai/parsers/creative_voice_file.py +342 -0
- polyfile/kaitai/parsers/dbf.py +274 -0
- polyfile/kaitai/parsers/dcmp_0.py +664 -0
- polyfile/kaitai/parsers/dcmp_1.py +422 -0
- polyfile/kaitai/parsers/dcmp_2.py +312 -0
- polyfile/kaitai/parsers/dcmp_variable_length_integer.py +66 -0
- polyfile/kaitai/parsers/dex.py +1086 -0
- polyfile/kaitai/parsers/dicom.py +4370 -0
- polyfile/kaitai/parsers/dime_message.py +201 -0
- polyfile/kaitai/parsers/dns_packet.py +569 -0
- polyfile/kaitai/parsers/doom_wad.py +654 -0
- polyfile/kaitai/parsers/dos_datetime.py +191 -0
- polyfile/kaitai/parsers/dos_mz.py +172 -0
- polyfile/kaitai/parsers/ds_store.py +513 -0
- polyfile/kaitai/parsers/dtb.py +310 -0
- polyfile/kaitai/parsers/dune_2_pak.py +126 -0
- polyfile/kaitai/parsers/edid.py +472 -0
- polyfile/kaitai/parsers/efivar_signature_list.py +331 -0
- polyfile/kaitai/parsers/elf.py +2482 -0
- polyfile/kaitai/parsers/ethernet_frame.py +114 -0
- polyfile/kaitai/parsers/exif.py +723 -0
- polyfile/kaitai/parsers/ext2.py +537 -0
- polyfile/kaitai/parsers/fallout2_dat.py +187 -0
- polyfile/kaitai/parsers/fallout_dat.py +156 -0
- polyfile/kaitai/parsers/fasttracker_xm_module.py +558 -0
- polyfile/kaitai/parsers/ftl_dat.py +90 -0
- polyfile/kaitai/parsers/genmidi_op2.py +161 -0
- polyfile/kaitai/parsers/gettext_mo.py +541 -0
- polyfile/kaitai/parsers/gif.py +492 -0
- polyfile/kaitai/parsers/gimp_brush.py +244 -0
- polyfile/kaitai/parsers/glibc_utmp.py +114 -0
- polyfile/kaitai/parsers/gltf_binary.py +132 -0
- polyfile/kaitai/parsers/google_protobuf.py +151 -0
- polyfile/kaitai/parsers/gpt_partition_table.py +175 -0
- polyfile/kaitai/parsers/gran_turismo_vol.py +140 -0
- polyfile/kaitai/parsers/grub2_font.py +337 -0
- polyfile/kaitai/parsers/gzip.py +232 -0
- polyfile/kaitai/parsers/hashcat_restore.py +60 -0
- polyfile/kaitai/parsers/hccap.py +111 -0
- polyfile/kaitai/parsers/hccapx.py +103 -0
- polyfile/kaitai/parsers/heaps_pak.py +177 -0
- polyfile/kaitai/parsers/heroes_of_might_and_magic_agg.py +116 -0
- polyfile/kaitai/parsers/heroes_of_might_and_magic_bmp.py +34 -0
- polyfile/kaitai/parsers/icmp_packet.py +136 -0
- polyfile/kaitai/parsers/ico.py +129 -0
- polyfile/kaitai/parsers/id3v1_1.py +220 -0
- polyfile/kaitai/parsers/id3v2_3.py +324 -0
- polyfile/kaitai/parsers/id3v2_4.py +423 -0
- polyfile/kaitai/parsers/ines.py +282 -0
- polyfile/kaitai/parsers/ipv4_packet.py +158 -0
- polyfile/kaitai/parsers/ipv6_packet.py +55 -0
- polyfile/kaitai/parsers/iso9660.py +544 -0
- polyfile/kaitai/parsers/java_class.py +1113 -0
- polyfile/kaitai/parsers/jpeg.py +361 -0
- polyfile/kaitai/parsers/luks.py +149 -0
- polyfile/kaitai/parsers/lzh.py +165 -0
- polyfile/kaitai/parsers/mac_os_resource_snd.py +493 -0
- polyfile/kaitai/parsers/mach_o.py +3033 -0
- polyfile/kaitai/parsers/mach_o_fat.py +92 -0
- polyfile/kaitai/parsers/magicavoxel_vox.py +391 -0
- polyfile/kaitai/parsers/manifest.json +1 -0
- polyfile/kaitai/parsers/mbr_partition_table.py +119 -0
- polyfile/kaitai/parsers/mcap.py +1015 -0
- polyfile/kaitai/parsers/microsoft_cfb.py +293 -0
- polyfile/kaitai/parsers/microsoft_network_monitor_v2.py +309 -0
- polyfile/kaitai/parsers/microsoft_pe.py +765 -0
- polyfile/kaitai/parsers/mifare_classic.py +706 -0
- polyfile/kaitai/parsers/minecraft_nbt.py +449 -0
- polyfile/kaitai/parsers/monomakh_sapr_chg.py +69 -0
- polyfile/kaitai/parsers/mozilla_mar.py +239 -0
- polyfile/kaitai/parsers/mp4.py +333 -0
- polyfile/kaitai/parsers/msgpack.py +467 -0
- polyfile/kaitai/parsers/nitf.py +1189 -0
- polyfile/kaitai/parsers/nt_mdt_pal.py +155 -0
- polyfile/kaitai/parsers/ogg.py +118 -0
- polyfile/kaitai/parsers/openpgp_message.py +993 -0
- polyfile/kaitai/parsers/packet_ppi.py +515 -0
- polyfile/kaitai/parsers/pcap.py +344 -0
- polyfile/kaitai/parsers/pcf_font.py +506 -0
- polyfile/kaitai/parsers/pcx.py +195 -0
- polyfile/kaitai/parsers/pcx_dcx.py +79 -0
- polyfile/kaitai/parsers/phar_without_stub.py +399 -0
- polyfile/kaitai/parsers/php_serialized_value.py +505 -0
- polyfile/kaitai/parsers/png.py +721 -0
- polyfile/kaitai/parsers/protocol_body.py +260 -0
- polyfile/kaitai/parsers/psx_tim.py +104 -0
- polyfile/kaitai/parsers/python_pickle.py +718 -0
- polyfile/kaitai/parsers/python_pyc_27.py +510 -0
- polyfile/kaitai/parsers/quake_mdl.py +441 -0
- polyfile/kaitai/parsers/quake_pak.py +112 -0
- polyfile/kaitai/parsers/quicktime_mov.py +634 -0
- polyfile/kaitai/parsers/rar.py +265 -0
- polyfile/kaitai/parsers/regf.py +569 -0
- polyfile/kaitai/parsers/renderware_binary_stream.py +877 -0
- polyfile/kaitai/parsers/resource_fork.py +611 -0
- polyfile/kaitai/parsers/respack.py +57 -0
- polyfile/kaitai/parsers/riff.py +409 -0
- polyfile/kaitai/parsers/rpm.py +964 -0
- polyfile/kaitai/parsers/rtcp_payload.py +579 -0
- polyfile/kaitai/parsers/rtp_packet.py +150 -0
- polyfile/kaitai/parsers/rtpdump.py +115 -0
- polyfile/kaitai/parsers/ruby_marshal.py +423 -0
- polyfile/kaitai/parsers/s3m.py +493 -0
- polyfile/kaitai/parsers/saints_row_2_vpp_pc.py +254 -0
- polyfile/kaitai/parsers/shapefile_index.py +174 -0
- polyfile/kaitai/parsers/shapefile_main.py +893 -0
- polyfile/kaitai/parsers/some_ip.py +209 -0
- polyfile/kaitai/parsers/some_ip_container.py +37 -0
- polyfile/kaitai/parsers/some_ip_sd.py +86 -0
- polyfile/kaitai/parsers/some_ip_sd_entries.py +160 -0
- polyfile/kaitai/parsers/some_ip_sd_options.py +374 -0
- polyfile/kaitai/parsers/specpr.py +404 -0
- polyfile/kaitai/parsers/sqlite3.py +472 -0
- polyfile/kaitai/parsers/ssh_public_key.py +252 -0
- polyfile/kaitai/parsers/standard_midi_file.py +390 -0
- polyfile/kaitai/parsers/stl.py +111 -0
- polyfile/kaitai/parsers/sudoers_ts.py +201 -0
- polyfile/kaitai/parsers/swf.py +406 -0
- polyfile/kaitai/parsers/systemd_journal.py +361 -0
- polyfile/kaitai/parsers/tcp_segment.py +57 -0
- polyfile/kaitai/parsers/tga.py +213 -0
- polyfile/kaitai/parsers/tls_client_hello.py +293 -0
- polyfile/kaitai/parsers/tr_dos_image.py +322 -0
- polyfile/kaitai/parsers/tsm.py +198 -0
- polyfile/kaitai/parsers/ttf.py +1847 -0
- polyfile/kaitai/parsers/udp_datagram.py +42 -0
- polyfile/kaitai/parsers/uefi_te.py +236 -0
- polyfile/kaitai/parsers/uimage.py +198 -0
- polyfile/kaitai/parsers/utf8_string.py +137 -0
- polyfile/kaitai/parsers/vfat.py +410 -0
- polyfile/kaitai/parsers/vlq_base128_be.py +104 -0
- polyfile/kaitai/parsers/vlq_base128_le.py +129 -0
- polyfile/kaitai/parsers/vmware_vmdk.py +167 -0
- polyfile/kaitai/parsers/vp8_ivf.py +112 -0
- polyfile/kaitai/parsers/warcraft_2_pud.py +423 -0
- polyfile/kaitai/parsers/wav.py +1014 -0
- polyfile/kaitai/parsers/websocket.py +167 -0
- polyfile/kaitai/parsers/windows_evt_log.py +304 -0
- polyfile/kaitai/parsers/windows_lnk_file.py +467 -0
- polyfile/kaitai/parsers/windows_minidump.py +575 -0
- polyfile/kaitai/parsers/windows_resource_file.py +243 -0
- polyfile/kaitai/parsers/windows_shell_items.py +190 -0
- polyfile/kaitai/parsers/windows_systemtime.py +52 -0
- polyfile/kaitai/parsers/wmf.py +502 -0
- polyfile/kaitai/parsers/xar.py +181 -0
- polyfile/kaitai/parsers/xwd.py +189 -0
- polyfile/kaitai/parsers/zip.py +685 -0
- polyfile/kaitai/parsers/zisofs.py +158 -0
- polyfile/kaitai/parsers/zx_spectrum_tap.py +184 -0
- polyfile/kaitaimatcher.py +113 -0
- polyfile/languagematcher.py +217 -0
- polyfile/logger.py +135 -0
- polyfile/magic.py +2983 -0
- polyfile/magic_defs/COPYING +29 -0
- polyfile/magic_defs/__init__.py +0 -0
- polyfile/magic_defs/acorn +102 -0
- polyfile/magic_defs/adi +13 -0
- polyfile/magic_defs/adventure +122 -0
- polyfile/magic_defs/aes +29 -0
- polyfile/magic_defs/algol68 +35 -0
- polyfile/magic_defs/allegro +9 -0
- polyfile/magic_defs/alliant +18 -0
- polyfile/magic_defs/alpha +32 -0
- polyfile/magic_defs/amanda +12 -0
- polyfile/magic_defs/amigaos +218 -0
- polyfile/magic_defs/android +259 -0
- polyfile/magic_defs/animation +1197 -0
- polyfile/magic_defs/aout +46 -0
- polyfile/magic_defs/apache +28 -0
- polyfile/magic_defs/apl +7 -0
- polyfile/magic_defs/apple +773 -0
- polyfile/magic_defs/application +7 -0
- polyfile/magic_defs/applix +13 -0
- polyfile/magic_defs/apt +52 -0
- polyfile/magic_defs/archive +2586 -0
- polyfile/magic_defs/aria +38 -0
- polyfile/magic_defs/arm +50 -0
- polyfile/magic_defs/asf +132 -0
- polyfile/magic_defs/assembler +18 -0
- polyfile/magic_defs/asterix +18 -0
- polyfile/magic_defs/att3b +41 -0
- polyfile/magic_defs/audio +1291 -0
- polyfile/magic_defs/avm +33 -0
- polyfile/magic_defs/basis +18 -0
- polyfile/magic_defs/beetle +7 -0
- polyfile/magic_defs/ber +65 -0
- polyfile/magic_defs/bflt +14 -0
- polyfile/magic_defs/bhl +10 -0
- polyfile/magic_defs/bioinformatics +178 -0
- polyfile/magic_defs/biosig +154 -0
- polyfile/magic_defs/blackberry +8 -0
- polyfile/magic_defs/blcr +25 -0
- polyfile/magic_defs/blender +50 -0
- polyfile/magic_defs/blit +24 -0
- polyfile/magic_defs/bm +10 -0
- polyfile/magic_defs/bout +11 -0
- polyfile/magic_defs/bsdi +33 -0
- polyfile/magic_defs/bsi +10 -0
- polyfile/magic_defs/btsnoop +13 -0
- polyfile/magic_defs/burp +7 -0
- polyfile/magic_defs/bytecode +41 -0
- polyfile/magic_defs/c-lang +110 -0
- polyfile/magic_defs/c64 +531 -0
- polyfile/magic_defs/cad +437 -0
- polyfile/magic_defs/cafebabe +107 -0
- polyfile/magic_defs/cbor +21 -0
- polyfile/magic_defs/ccf +14 -0
- polyfile/magic_defs/cddb +12 -0
- polyfile/magic_defs/chord +15 -0
- polyfile/magic_defs/cisco +12 -0
- polyfile/magic_defs/citrus +12 -0
- polyfile/magic_defs/clarion +27 -0
- polyfile/magic_defs/claris +48 -0
- polyfile/magic_defs/clipper +65 -0
- polyfile/magic_defs/clojure +30 -0
- polyfile/magic_defs/coff +98 -0
- polyfile/magic_defs/commands +201 -0
- polyfile/magic_defs/communications +22 -0
- polyfile/magic_defs/compress +461 -0
- polyfile/magic_defs/console +1213 -0
- polyfile/magic_defs/convex +69 -0
- polyfile/magic_defs/coverage +91 -0
- polyfile/magic_defs/cracklib +14 -0
- polyfile/magic_defs/crypto +31 -0
- polyfile/magic_defs/csv +8 -0
- polyfile/magic_defs/ctags +6 -0
- polyfile/magic_defs/ctf +23 -0
- polyfile/magic_defs/cubemap +8 -0
- polyfile/magic_defs/cups +56 -0
- polyfile/magic_defs/dact +11 -0
- polyfile/magic_defs/database +886 -0
- polyfile/magic_defs/dataone +47 -0
- polyfile/magic_defs/dbpf +15 -0
- polyfile/magic_defs/der +146 -0
- polyfile/magic_defs/diamond +12 -0
- polyfile/magic_defs/dif +33 -0
- polyfile/magic_defs/diff +41 -0
- polyfile/magic_defs/digital +59 -0
- polyfile/magic_defs/dolby +69 -0
- polyfile/magic_defs/dsf +25 -0
- polyfile/magic_defs/dump +96 -0
- polyfile/magic_defs/dwarfs +45 -0
- polyfile/magic_defs/dyadic +61 -0
- polyfile/magic_defs/ebml +8 -0
- polyfile/magic_defs/edid +11 -0
- polyfile/magic_defs/editors +43 -0
- polyfile/magic_defs/efi +15 -0
- polyfile/magic_defs/elf +379 -0
- polyfile/magic_defs/encore +22 -0
- polyfile/magic_defs/epoc +62 -0
- polyfile/magic_defs/erlang +21 -0
- polyfile/magic_defs/espressif +57 -0
- polyfile/magic_defs/esri +28 -0
- polyfile/magic_defs/etf +33 -0
- polyfile/magic_defs/fcs +9 -0
- polyfile/magic_defs/filesystems +2694 -0
- polyfile/magic_defs/finger +16 -0
- polyfile/magic_defs/firmware +133 -0
- polyfile/magic_defs/flash +62 -0
- polyfile/magic_defs/flif +36 -0
- polyfile/magic_defs/fonts +449 -0
- polyfile/magic_defs/forth +82 -0
- polyfile/magic_defs/fortran +9 -0
- polyfile/magic_defs/frame +62 -0
- polyfile/magic_defs/freebsd +164 -0
- polyfile/magic_defs/fsav +128 -0
- polyfile/magic_defs/fusecompress +12 -0
- polyfile/magic_defs/games +696 -0
- polyfile/magic_defs/gcc +17 -0
- polyfile/magic_defs/gconv +10 -0
- polyfile/magic_defs/gentoo +85 -0
- polyfile/magic_defs/geo +166 -0
- polyfile/magic_defs/geos +20 -0
- polyfile/magic_defs/gimp +77 -0
- polyfile/magic_defs/git +13 -0
- polyfile/magic_defs/glibc +21 -0
- polyfile/magic_defs/gnome +59 -0
- polyfile/magic_defs/gnu +173 -0
- polyfile/magic_defs/gnumeric +8 -0
- polyfile/magic_defs/gpt +240 -0
- polyfile/magic_defs/gpu +28 -0
- polyfile/magic_defs/grace +21 -0
- polyfile/magic_defs/graphviz +12 -0
- polyfile/magic_defs/gringotts +48 -0
- polyfile/magic_defs/guile +13 -0
- polyfile/magic_defs/hardware +12 -0
- polyfile/magic_defs/hitachi-sh +30 -0
- polyfile/magic_defs/hp +433 -0
- polyfile/magic_defs/human68k +26 -0
- polyfile/magic_defs/ibm370 +52 -0
- polyfile/magic_defs/ibm6000 +35 -0
- polyfile/magic_defs/icc +214 -0
- polyfile/magic_defs/iff +80 -0
- polyfile/magic_defs/images +4210 -0
- polyfile/magic_defs/inform +9 -0
- polyfile/magic_defs/intel +310 -0
- polyfile/magic_defs/interleaf +9 -0
- polyfile/magic_defs/island +10 -0
- polyfile/magic_defs/ispell +63 -0
- polyfile/magic_defs/isz +15 -0
- polyfile/magic_defs/java +52 -0
- polyfile/magic_defs/javascript +171 -0
- polyfile/magic_defs/jpeg +252 -0
- polyfile/magic_defs/json +8 -0
- polyfile/magic_defs/karma +9 -0
- polyfile/magic_defs/kde +11 -0
- polyfile/magic_defs/keepass +20 -0
- polyfile/magic_defs/kerberos +45 -0
- polyfile/magic_defs/kicad +85 -0
- polyfile/magic_defs/kml +34 -0
- polyfile/magic_defs/lammps +64 -0
- polyfile/magic_defs/lecter +6 -0
- polyfile/magic_defs/lex +12 -0
- polyfile/magic_defs/lif +50 -0
- polyfile/magic_defs/linux +557 -0
- polyfile/magic_defs/lisp +78 -0
- polyfile/magic_defs/llvm +22 -0
- polyfile/magic_defs/locoscript +12 -0
- polyfile/magic_defs/lua +31 -0
- polyfile/magic_defs/luks +126 -0
- polyfile/magic_defs/m4 +11 -0
- polyfile/magic_defs/mach +303 -0
- polyfile/magic_defs/macintosh +505 -0
- polyfile/magic_defs/macos +7 -0
- polyfile/magic_defs/magic +10 -0
- polyfile/magic_defs/magic.mgc +0 -0
- polyfile/magic_defs/mail.news +132 -0
- polyfile/magic_defs/make +21 -0
- polyfile/magic_defs/map +413 -0
- polyfile/magic_defs/maple +109 -0
- polyfile/magic_defs/marc21 +30 -0
- polyfile/magic_defs/mathcad +8 -0
- polyfile/magic_defs/mathematica +188 -0
- polyfile/magic_defs/matroska +17 -0
- polyfile/magic_defs/mcrypt +52 -0
- polyfile/magic_defs/measure +44 -0
- polyfile/magic_defs/mercurial +13 -0
- polyfile/magic_defs/metastore +8 -0
- polyfile/magic_defs/meteorological +53 -0
- polyfile/magic_defs/microfocus +21 -0
- polyfile/magic_defs/mime +9 -0
- polyfile/magic_defs/mips +120 -0
- polyfile/magic_defs/mirage +8 -0
- polyfile/magic_defs/misctools +140 -0
- polyfile/magic_defs/mkid +11 -0
- polyfile/magic_defs/mlssa +8 -0
- polyfile/magic_defs/mmdf +6 -0
- polyfile/magic_defs/modem +92 -0
- polyfile/magic_defs/modulefile +9 -0
- polyfile/magic_defs/motorola +71 -0
- polyfile/magic_defs/mozilla +37 -0
- polyfile/magic_defs/msdos +2304 -0
- polyfile/magic_defs/msooxml +68 -0
- polyfile/magic_defs/msvc +222 -0
- polyfile/magic_defs/msx +309 -0
- polyfile/magic_defs/mup +24 -0
- polyfile/magic_defs/music +17 -0
- polyfile/magic_defs/nasa +7 -0
- polyfile/magic_defs/natinst +24 -0
- polyfile/magic_defs/ncr +49 -0
- polyfile/magic_defs/neko +12 -0
- polyfile/magic_defs/netbsd +251 -0
- polyfile/magic_defs/netscape +26 -0
- polyfile/magic_defs/netware +11 -0
- polyfile/magic_defs/news +13 -0
- polyfile/magic_defs/nifty +202 -0
- polyfile/magic_defs/nim-lang +29 -0
- polyfile/magic_defs/nitpicker +14 -0
- polyfile/magic_defs/numpy +9 -0
- polyfile/magic_defs/oasis +12 -0
- polyfile/magic_defs/ocaml +14 -0
- polyfile/magic_defs/octave +6 -0
- polyfile/magic_defs/ole2compounddocs +760 -0
- polyfile/magic_defs/olf +98 -0
- polyfile/magic_defs/openfst +17 -0
- polyfile/magic_defs/opentimestamps +16 -0
- polyfile/magic_defs/oric +16 -0
- polyfile/magic_defs/os2 +186 -0
- polyfile/magic_defs/os400 +39 -0
- polyfile/magic_defs/os9 +80 -0
- polyfile/magic_defs/osf1 +10 -0
- polyfile/magic_defs/palm +156 -0
- polyfile/magic_defs/parix +13 -0
- polyfile/magic_defs/parrot +22 -0
- polyfile/magic_defs/pascal +39 -0
- polyfile/magic_defs/pbf +11 -0
- polyfile/magic_defs/pbm +8 -0
- polyfile/magic_defs/pc88 +24 -0
- polyfile/magic_defs/pc98 +77 -0
- polyfile/magic_defs/pci_ids +116 -0
- polyfile/magic_defs/pcjr +8 -0
- polyfile/magic_defs/pdf +51 -0
- polyfile/magic_defs/pdp +42 -0
- polyfile/magic_defs/perl +100 -0
- polyfile/magic_defs/pgf +52 -0
- polyfile/magic_defs/pgp +581 -0
- polyfile/magic_defs/pgp-binary-keys +388 -0
- polyfile/magic_defs/pkgadd +7 -0
- polyfile/magic_defs/plan9 +25 -0
- polyfile/magic_defs/playdate +57 -0
- polyfile/magic_defs/plus5 +18 -0
- polyfile/magic_defs/pmem +46 -0
- polyfile/magic_defs/polyfile_zip +5 -0
- polyfile/magic_defs/polyml +23 -0
- polyfile/magic_defs/printer +269 -0
- polyfile/magic_defs/project +10 -0
- polyfile/magic_defs/psdbms +14 -0
- polyfile/magic_defs/psl +14 -0
- polyfile/magic_defs/pulsar +13 -0
- polyfile/magic_defs/puzzle +17 -0
- polyfile/magic_defs/pwsafe +14 -0
- polyfile/magic_defs/pyramid +12 -0
- polyfile/magic_defs/python +305 -0
- polyfile/magic_defs/qt +30 -0
- polyfile/magic_defs/revision +66 -0
- polyfile/magic_defs/riff +840 -0
- polyfile/magic_defs/rinex +44 -0
- polyfile/magic_defs/ringdove +45 -0
- polyfile/magic_defs/rpi +52 -0
- polyfile/magic_defs/rpm +45 -0
- polyfile/magic_defs/rpmsg +7 -0
- polyfile/magic_defs/rst +11 -0
- polyfile/magic_defs/rtf +94 -0
- polyfile/magic_defs/ruby +55 -0
- polyfile/magic_defs/rust +21 -0
- polyfile/magic_defs/sc +7 -0
- polyfile/magic_defs/sccs +24 -0
- polyfile/magic_defs/scientific +144 -0
- polyfile/magic_defs/securitycerts +6 -0
- polyfile/magic_defs/selinux +24 -0
- polyfile/magic_defs/sendmail +37 -0
- polyfile/magic_defs/sequent +42 -0
- polyfile/magic_defs/sereal +35 -0
- polyfile/magic_defs/sgi +144 -0
- polyfile/magic_defs/sgml +161 -0
- polyfile/magic_defs/sharc +23 -0
- polyfile/magic_defs/sinclair +40 -0
- polyfile/magic_defs/sisu +18 -0
- polyfile/magic_defs/sketch +6 -0
- polyfile/magic_defs/smalltalk +25 -0
- polyfile/magic_defs/smile +34 -0
- polyfile/magic_defs/sniffer +482 -0
- polyfile/magic_defs/softquad +40 -0
- polyfile/magic_defs/sosi +40 -0
- polyfile/magic_defs/spec +21 -0
- polyfile/magic_defs/spectrum +184 -0
- polyfile/magic_defs/sql +288 -0
- polyfile/magic_defs/ssh +39 -0
- polyfile/magic_defs/ssl +20 -0
- polyfile/magic_defs/statistics +45 -0
- polyfile/magic_defs/subtitle +38 -0
- polyfile/magic_defs/sun +141 -0
- polyfile/magic_defs/svf +5 -0
- polyfile/magic_defs/sylk +36 -0
- polyfile/magic_defs/symbos +42 -0
- polyfile/magic_defs/sysex +429 -0
- polyfile/magic_defs/tcl +29 -0
- polyfile/magic_defs/teapot +6 -0
- polyfile/magic_defs/terminfo +63 -0
- polyfile/magic_defs/tex +141 -0
- polyfile/magic_defs/tgif +7 -0
- polyfile/magic_defs/ti-8x +239 -0
- polyfile/magic_defs/timezone +42 -0
- polyfile/magic_defs/tplink +95 -0
- polyfile/magic_defs/troff +38 -0
- polyfile/magic_defs/tuxedo +8 -0
- polyfile/magic_defs/typeset +8 -0
- polyfile/magic_defs/uf2 +72 -0
- polyfile/magic_defs/unicode +15 -0
- polyfile/magic_defs/unisig +12 -0
- polyfile/magic_defs/unknown +34 -0
- polyfile/magic_defs/usd +21 -0
- polyfile/magic_defs/uterus +16 -0
- polyfile/magic_defs/uuencode +28 -0
- polyfile/magic_defs/vacuum-cleaner +54 -0
- polyfile/magic_defs/varied.out +46 -0
- polyfile/magic_defs/varied.script +21 -0
- polyfile/magic_defs/vax +32 -0
- polyfile/magic_defs/vicar +17 -0
- polyfile/magic_defs/virtual +307 -0
- polyfile/magic_defs/virtutech +12 -0
- polyfile/magic_defs/visx +32 -0
- polyfile/magic_defs/vms +30 -0
- polyfile/magic_defs/vmware +6 -0
- polyfile/magic_defs/vorbis +155 -0
- polyfile/magic_defs/vxl +14 -0
- polyfile/magic_defs/warc +16 -0
- polyfile/magic_defs/weak +16 -0
- polyfile/magic_defs/web +18 -0
- polyfile/magic_defs/webassembly +17 -0
- polyfile/magic_defs/windows +1811 -0
- polyfile/magic_defs/wireless +7 -0
- polyfile/magic_defs/wordprocessors +630 -0
- polyfile/magic_defs/wsdl +23 -0
- polyfile/magic_defs/x68000 +25 -0
- polyfile/magic_defs/xdelta +13 -0
- polyfile/magic_defs/xenix +106 -0
- polyfile/magic_defs/xilinx +58 -0
- polyfile/magic_defs/xo65 +37 -0
- polyfile/magic_defs/xwindows +43 -0
- polyfile/magic_defs/yara +17 -0
- polyfile/magic_defs/zfs +96 -0
- polyfile/magic_defs/zilog +12 -0
- polyfile/magic_defs/zip +126 -0
- polyfile/magic_defs/zyxel +17 -0
- polyfile/nes.py +144 -0
- polyfile/nitf.py +15 -0
- polyfile/pdf.py +1264 -0
- polyfile/pickles.py +45 -0
- polyfile/polyfile.py +409 -0
- polyfile/profiling.py +115 -0
- polyfile/repl.py +624 -0
- polyfile/search.py +310 -0
- polyfile/serialization.py +323 -0
- polyfile/structmatcher.py +46 -0
- polyfile/structs.py +281 -0
- polyfile/templates/download.js +162 -0
- polyfile/templates/hexdump.css +268 -0
- polyfile/templates/hexdump.js +756 -0
- polyfile/templates/jquery-3.4.1.min.js +2 -0
- polyfile/templates/template.html +119 -0
- polyfile/wildcards.py +62 -0
- polyfile/zipmatcher.py +183 -0
- polyfile_weave-0.5.5.dist-info/METADATA +173 -0
- polyfile_weave-0.5.5.dist-info/RECORD +585 -0
- polyfile_weave-0.5.5.dist-info/WHEEL +5 -0
- polyfile_weave-0.5.5.dist-info/entry_points.txt +2 -0
- polyfile_weave-0.5.5.dist-info/licenses/LICENSE +202 -0
- polyfile_weave-0.5.5.dist-info/top_level.txt +2 -0
- polymerge/__init__.py +1 -0
- polymerge/__main__.py +296 -0
- polymerge/cfg.py +127 -0
- polymerge/polymerge.py +227 -0
- polymerge/polytracker.py +190 -0
polyfile/search.py
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
from collections import deque
|
|
2
|
+
import collections.abc
|
|
3
|
+
from typing import IO, Mapping, Sequence, Union
|
|
4
|
+
|
|
5
|
+
from . import serialization
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@serialization.serializable
|
|
9
|
+
class TrieNode:
|
|
10
|
+
def __init__(self, value=None, sources=None, _children=None):
|
|
11
|
+
if _children is None:
|
|
12
|
+
self._children: Mapping[object, TrieNode] = {}
|
|
13
|
+
else:
|
|
14
|
+
self._children = _children
|
|
15
|
+
self.value = value
|
|
16
|
+
if sources is not None:
|
|
17
|
+
self._sources = set(sources)
|
|
18
|
+
else:
|
|
19
|
+
self._sources = set()
|
|
20
|
+
|
|
21
|
+
def __repr__(self):
|
|
22
|
+
return f"{self.__class__.__name__}(value={self.value!r}, sources={self.sources!r}, _children={self._children!r})"
|
|
23
|
+
|
|
24
|
+
def __len__(self):
|
|
25
|
+
return len(self._children)
|
|
26
|
+
|
|
27
|
+
def __iter__(self):
|
|
28
|
+
return iter(self._children.values())
|
|
29
|
+
|
|
30
|
+
def __hash__(self):
|
|
31
|
+
return hash(self.value)
|
|
32
|
+
|
|
33
|
+
def __eq__(self, other):
|
|
34
|
+
return self.value == other.value
|
|
35
|
+
|
|
36
|
+
def __ne__(self, other):
|
|
37
|
+
return not (self == other)
|
|
38
|
+
|
|
39
|
+
def __getitem__(self, key):
|
|
40
|
+
return self._children[key]
|
|
41
|
+
|
|
42
|
+
def __contains__(self, value):
|
|
43
|
+
if not isinstance(value, collections.abc.Sequence):
|
|
44
|
+
first, remainder, n = value, (), 1
|
|
45
|
+
else:
|
|
46
|
+
first, remainder, n = self._car_cdr_len(value)
|
|
47
|
+
if n == 1:
|
|
48
|
+
return first in self._children
|
|
49
|
+
else:
|
|
50
|
+
return self._find(first, remainder, n)
|
|
51
|
+
|
|
52
|
+
@staticmethod
|
|
53
|
+
def _car_cdr_len(sequence):
|
|
54
|
+
n = len(sequence)
|
|
55
|
+
if n == 0:
|
|
56
|
+
first = None
|
|
57
|
+
else:
|
|
58
|
+
first = sequence[0]
|
|
59
|
+
return first, sequence[1:], n
|
|
60
|
+
|
|
61
|
+
def _find(self, first, remainder, n):
|
|
62
|
+
if n == 0:
|
|
63
|
+
return len(self._sources) > 0
|
|
64
|
+
if first not in self._children:
|
|
65
|
+
return False
|
|
66
|
+
return self[first]._find(*self._car_cdr_len(remainder))
|
|
67
|
+
|
|
68
|
+
def find(self, key):
|
|
69
|
+
if isinstance(key, collections.abc.Sequence):
|
|
70
|
+
return self._find(*self._car_cdr_len(key))
|
|
71
|
+
else:
|
|
72
|
+
return self._find(key, (), 1)
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def children(self):
|
|
76
|
+
return dict(self._children)
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def sources(self):
|
|
80
|
+
return frozenset(self._sources)
|
|
81
|
+
|
|
82
|
+
def _add_child(self, value, sources=None):
|
|
83
|
+
new_child = TrieNode(value, sources)
|
|
84
|
+
self._children[value] = new_child
|
|
85
|
+
return new_child
|
|
86
|
+
|
|
87
|
+
def _add(self, sequence, source):
|
|
88
|
+
node = self
|
|
89
|
+
while True:
|
|
90
|
+
first, sequence, n = self._car_cdr_len(sequence)
|
|
91
|
+
if n == 0:
|
|
92
|
+
break
|
|
93
|
+
if first in node:
|
|
94
|
+
node = node[first]
|
|
95
|
+
else:
|
|
96
|
+
node = node._add_child(first)
|
|
97
|
+
node._sources.add(source)
|
|
98
|
+
return node
|
|
99
|
+
|
|
100
|
+
def add(self, sequence, source=None):
|
|
101
|
+
if source is None:
|
|
102
|
+
source = sequence
|
|
103
|
+
return self._add(sequence, source)
|
|
104
|
+
|
|
105
|
+
def find_prefix(self, prefix):
|
|
106
|
+
first, remainder, n = self._car_cdr_len(prefix)
|
|
107
|
+
if n == 0:
|
|
108
|
+
yield from iter(self._sources)
|
|
109
|
+
for child in self:
|
|
110
|
+
yield from child.find_prefix(prefix)
|
|
111
|
+
else:
|
|
112
|
+
if first in self._children:
|
|
113
|
+
yield from self[first].find_prefix(remainder)
|
|
114
|
+
|
|
115
|
+
def bfs(self):
|
|
116
|
+
queue = deque([self])
|
|
117
|
+
while queue:
|
|
118
|
+
head = queue.popleft()
|
|
119
|
+
yield head
|
|
120
|
+
queue.extend(head._children.values())
|
|
121
|
+
|
|
122
|
+
def dfs(self):
|
|
123
|
+
stack = [self]
|
|
124
|
+
visited = set()
|
|
125
|
+
while stack:
|
|
126
|
+
tail = stack.pop()
|
|
127
|
+
yield tail
|
|
128
|
+
children = tail._children.values()
|
|
129
|
+
stack.extend(child for child in children if id(child) not in visited)
|
|
130
|
+
visited |= set(id(c) for c in children)
|
|
131
|
+
|
|
132
|
+
def serialize(self):
|
|
133
|
+
return self.value, self._sources, self._children
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@serialization.serializable
|
|
137
|
+
class ACNode(TrieNode):
|
|
138
|
+
"""A data structure for implementing the Aho-Corasick multi-string matching algorithm"""
|
|
139
|
+
def __init__(self, value=None, sources=None, _children=None, parent=None, _fall=None):
|
|
140
|
+
super().__init__(value=value, sources=sources, _children=_children)
|
|
141
|
+
self.parent = parent
|
|
142
|
+
self.fall = _fall
|
|
143
|
+
|
|
144
|
+
def serialize(self):
|
|
145
|
+
return super().serialize() + (self.parent, self.fall)
|
|
146
|
+
|
|
147
|
+
def __repr__(self):
|
|
148
|
+
if self.fall is not self:
|
|
149
|
+
return f"{self.__class__.__name__}(value={self.value!r}, sources={self.sources!r}, _children={self._children!r}), parent={self.parent!r}, _fall={self.fall!r}"
|
|
150
|
+
else:
|
|
151
|
+
return f"{self.__class__.__name__}(value={self.value!r}, sources={self.sources!r}, _children={self._children!r}), parent={self.parent!r}, _fall=self"
|
|
152
|
+
|
|
153
|
+
def _add_child(self, value, sources=None):
|
|
154
|
+
new_child = ACNode(value, sources, parent=self)
|
|
155
|
+
self._children[value] = new_child
|
|
156
|
+
return new_child
|
|
157
|
+
|
|
158
|
+
def finalize(self):
|
|
159
|
+
self.fall = self
|
|
160
|
+
for n in self.bfs():
|
|
161
|
+
if n is self:
|
|
162
|
+
continue
|
|
163
|
+
new_fall = n.parent.fall
|
|
164
|
+
while n.value not in new_fall and new_fall is not self:
|
|
165
|
+
new_fall = new_fall.fall
|
|
166
|
+
if n.value not in new_fall:
|
|
167
|
+
# there is no suffix
|
|
168
|
+
n.fall = self
|
|
169
|
+
else:
|
|
170
|
+
n.fall = new_fall[n.value]
|
|
171
|
+
if n.fall is n:
|
|
172
|
+
n.fall = self
|
|
173
|
+
|
|
174
|
+
def to_dot(self, include_falls=False):
|
|
175
|
+
"""Returns a Graphviz/Dot representation of this Trie"""
|
|
176
|
+
dot = "digraph G {\n"
|
|
177
|
+
node_ids = {}
|
|
178
|
+
falls = {}
|
|
179
|
+
for node in self.dfs():
|
|
180
|
+
assert node not in node_ids
|
|
181
|
+
nid = len(node_ids)
|
|
182
|
+
node_ids[id(node)] = nid
|
|
183
|
+
dot += f" node{nid}"
|
|
184
|
+
if node.value is None:
|
|
185
|
+
dot += f"[label=\"Root\"]"
|
|
186
|
+
else:
|
|
187
|
+
if node.value == ord('"'):
|
|
188
|
+
c = '\\"'
|
|
189
|
+
elif node.value == ord('\\'):
|
|
190
|
+
c = '\\\\'
|
|
191
|
+
elif 32 <= node.value <= 126:
|
|
192
|
+
c = chr(node.value)
|
|
193
|
+
else:
|
|
194
|
+
c = f"\\\\x{hex(node.value)[2:]}"
|
|
195
|
+
dot += f"[label=\"{c}\"]"
|
|
196
|
+
dot += ";\n"
|
|
197
|
+
if node.parent is not None:
|
|
198
|
+
dot += f" node{node_ids[id(node.parent)]} -> node{nid};\n"
|
|
199
|
+
if include_falls and node.fall is not None and node.fall is not node:
|
|
200
|
+
falls[id(node)] = id(node.fall)
|
|
201
|
+
|
|
202
|
+
for nodeid, fallid in falls.items():
|
|
203
|
+
dot += f" node{node_ids[nodeid]} -> node{node_ids[fallid]} [style=dashed,label=\"fall\"];\n"
|
|
204
|
+
dot += "}\n"
|
|
205
|
+
return dot
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
class MultiSequenceSearch:
|
|
209
|
+
"""A datastructure for efficiently searching a sequence for multiple strings"""
|
|
210
|
+
def __init__(self, *sequences_to_find):
|
|
211
|
+
self.trie = ACNode()
|
|
212
|
+
for seq in sequences_to_find:
|
|
213
|
+
self.trie.add(seq)
|
|
214
|
+
self.trie.finalize()
|
|
215
|
+
|
|
216
|
+
def save(self, output_stream: IO):
|
|
217
|
+
serialization.dump(self.trie, output_stream)
|
|
218
|
+
|
|
219
|
+
@staticmethod
|
|
220
|
+
def load(input_stream: IO):
|
|
221
|
+
mss = MultiSequenceSearch()
|
|
222
|
+
mss.trie = serialization.load(input_stream)
|
|
223
|
+
print(mss.trie)
|
|
224
|
+
exit(0)
|
|
225
|
+
return mss
|
|
226
|
+
|
|
227
|
+
def search(self, source_sequence: Union[Sequence, IO]):
|
|
228
|
+
"""The Aho-Corasick Algorithm"""
|
|
229
|
+
if hasattr(source_sequence, 'read'):
|
|
230
|
+
def iterator():
|
|
231
|
+
while True:
|
|
232
|
+
b = source_sequence.read(1)
|
|
233
|
+
if not b:
|
|
234
|
+
return
|
|
235
|
+
yield b[0]
|
|
236
|
+
else:
|
|
237
|
+
def iterator():
|
|
238
|
+
return iter(source_sequence)
|
|
239
|
+
|
|
240
|
+
state = self.trie
|
|
241
|
+
for stream_offset, c in enumerate(iterator()):
|
|
242
|
+
n = state
|
|
243
|
+
|
|
244
|
+
while c not in n and n is not self.trie:
|
|
245
|
+
n = n.fall
|
|
246
|
+
|
|
247
|
+
if n is self.trie:
|
|
248
|
+
if c in n:
|
|
249
|
+
n = n[c]
|
|
250
|
+
else:
|
|
251
|
+
n = n[c]
|
|
252
|
+
|
|
253
|
+
state = n
|
|
254
|
+
|
|
255
|
+
while n is not self.trie:
|
|
256
|
+
yield from ((stream_offset - len(source) + 1, source) for source in n.sources)
|
|
257
|
+
n = n.fall
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
class StartsWithMatcher:
|
|
261
|
+
def __init__(self, *sequences_to_find):
|
|
262
|
+
self.trie = TrieNode()
|
|
263
|
+
for seq in sequences_to_find:
|
|
264
|
+
self.trie.add(seq)
|
|
265
|
+
|
|
266
|
+
def search(self, source_sequence: Union[Sequence, IO]):
|
|
267
|
+
if hasattr(source_sequence, 'read'):
|
|
268
|
+
def iterator():
|
|
269
|
+
while True:
|
|
270
|
+
b = source_sequence.read(1)
|
|
271
|
+
if not b:
|
|
272
|
+
return
|
|
273
|
+
yield b[0]
|
|
274
|
+
else:
|
|
275
|
+
def iterator():
|
|
276
|
+
return iter(source_sequence)
|
|
277
|
+
|
|
278
|
+
state = self.trie
|
|
279
|
+
yield from ((0, s) for s in state.sources)
|
|
280
|
+
|
|
281
|
+
for c in iterator():
|
|
282
|
+
if c not in state:
|
|
283
|
+
return
|
|
284
|
+
|
|
285
|
+
state = state[c]
|
|
286
|
+
yield from ((0, s) for s in state.sources)
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
if __name__ == '__main__':
|
|
290
|
+
root = TrieNode()
|
|
291
|
+
root.add('The quick brown fox jumps over the lazy dog')
|
|
292
|
+
root.add('The quick person')
|
|
293
|
+
root.add('The best')
|
|
294
|
+
assert len(list(root.find_prefix('The'))) == 3
|
|
295
|
+
assert len(list(root.find_prefix('The quick'))) == 2
|
|
296
|
+
assert not root.find('The')
|
|
297
|
+
assert root.find('The best')
|
|
298
|
+
|
|
299
|
+
mss = MultiSequenceSearch(b'hack', b'hacker', b'crack', b'ack', b'kool')
|
|
300
|
+
to_search = b'This is a test to see if hack or hacker is in this string.'\
|
|
301
|
+
b'Can you crack it? If so, please ack, \'cause that would be kool.'
|
|
302
|
+
for offset, match in mss.search(to_search):
|
|
303
|
+
print(offset, match)
|
|
304
|
+
assert to_search[offset:offset+len(match)] == match
|
|
305
|
+
|
|
306
|
+
swm = StartsWithMatcher(b'hack', b'hacker', b'crack', b'ack', b'kool')
|
|
307
|
+
for match in swm.search(b'hacker'):
|
|
308
|
+
print(match)
|
|
309
|
+
|
|
310
|
+
print(ACNode.load(mss.trie.serialize()))
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
import io
|
|
3
|
+
from itertools import chain
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def write_int(i:int, stream):
|
|
7
|
+
bits = max(i.bit_length(), 1)
|
|
8
|
+
for bit_group in reversed(range((bits - 1) // 7 + 1)):
|
|
9
|
+
b = (i >> (bit_group * 7)) & 0b01111111
|
|
10
|
+
if bit_group == 0:
|
|
11
|
+
b |= 0b10000000
|
|
12
|
+
stream.write(bytes([b]))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def read_int(stream):
|
|
16
|
+
i = 0
|
|
17
|
+
while True:
|
|
18
|
+
i <<= 7
|
|
19
|
+
b = ord(stream.read(1))
|
|
20
|
+
i |= (b & 0b01111111)
|
|
21
|
+
if b & 0b10000000:
|
|
22
|
+
break
|
|
23
|
+
return i
|
|
24
|
+
|
|
25
|
+
ENCODINGS_BY_TYPE = {}
|
|
26
|
+
ENCODINGS_BY_ID = {}
|
|
27
|
+
CUSTOM_ENCODINGS = {}
|
|
28
|
+
CUSTOM_ENCODINGS_BY_ID = {}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def encode_int(i, _, stream):
|
|
32
|
+
write_int(i, stream)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def decode_int(_, stream):
|
|
36
|
+
return read_int(stream)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def encode_bytes(s, _, stream):
|
|
40
|
+
write_int(len(s), stream)
|
|
41
|
+
stream.write(s)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def encode_string(s:str, _, stream):
|
|
45
|
+
encode_bytes(s.encode('utf-8'), None, stream)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def decode_bytes(_, stream):
|
|
49
|
+
length = read_int(stream)
|
|
50
|
+
return stream.read(length)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def decode_string(_, stream):
|
|
54
|
+
return decode_bytes(None, stream).decode('utf-8')
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def encode_list(lst, obj_ids, stream):
|
|
58
|
+
for obj in lst:
|
|
59
|
+
write_int(obj_ids[id(obj)], stream)
|
|
60
|
+
write_int(EncodeTypes.END.encoding_id, stream)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
encode_tuple = encode_list
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
encode_set = encode_list
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
encode_frozenset = encode_list
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _decode_to_end(stream):
|
|
73
|
+
while True:
|
|
74
|
+
i = read_int(stream)
|
|
75
|
+
if i == EncodeTypes.END.encoding_id:
|
|
76
|
+
break
|
|
77
|
+
yield i
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def pairwise(iterable):
|
|
81
|
+
while True:
|
|
82
|
+
try:
|
|
83
|
+
a, b = next(iterable), next(iterable)
|
|
84
|
+
except StopIteration:
|
|
85
|
+
break
|
|
86
|
+
yield a, b
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def decode_list(objs, stream):
|
|
90
|
+
return [objs[i] for i in _decode_to_end(stream)]
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def decode_tuple(*args, **kwargs):
|
|
94
|
+
return tuple(decode_list(*args, **kwargs))
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def decode_set(*args, **kwargs):
|
|
98
|
+
return set(decode_list(*args, **kwargs))
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def decode_frozenset(*args, **kwargs):
|
|
102
|
+
return frozenset(decode_list(*args, **kwargs))
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def encode_dict(d: dict, obj_ids, stream):
|
|
106
|
+
for k, v in d.items():
|
|
107
|
+
write_int(obj_ids[id(k)], stream)
|
|
108
|
+
write_int(obj_ids[id(v)], stream)
|
|
109
|
+
write_int(EncodeTypes.END.encoding_id, stream)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def decode_dict(objs, stream):
|
|
113
|
+
return {objs[k]: objs[v] for k, v in pairwise(_decode_to_end(stream))}
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def encode_none(*args, **kwargs):
|
|
117
|
+
pass
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def decode_none(*args, **kwargs):
|
|
121
|
+
return None
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def encode_bool(b: bool, _, stream):
|
|
125
|
+
write_int(int(b), stream)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def decode_bool(_, stream):
|
|
129
|
+
return bool(read_int(stream))
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def encode_custom(c, obj_ids, stream):
|
|
133
|
+
write_int(CUSTOM_ENCODINGS[type(c)], stream)
|
|
134
|
+
encode_list(c.serialize(), obj_ids, stream)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def decode_custom(objs, stream):
|
|
138
|
+
custom_type = CUSTOM_ENCODINGS_BY_ID[read_int(stream)]
|
|
139
|
+
args = decode_list(objs, stream)
|
|
140
|
+
return custom_type(*args)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class _EndObject:
|
|
144
|
+
pass
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class _CustomObject:
|
|
148
|
+
pass
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def serializable(SerializableClass):
|
|
152
|
+
if not hasattr(SerializableClass, 'serialize'):
|
|
153
|
+
raise ValueError(f'Serializable class {SerializableClass} must implement the `serialize` member function')
|
|
154
|
+
new_id = len(CUSTOM_ENCODINGS)
|
|
155
|
+
CUSTOM_ENCODINGS[SerializableClass] = new_id
|
|
156
|
+
CUSTOM_ENCODINGS_BY_ID[new_id] = SerializableClass
|
|
157
|
+
return SerializableClass
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class EncodeTypes(Enum):
|
|
161
|
+
END = (0, _EndObject, None, None, None)
|
|
162
|
+
NONE = (1, type(None), encode_none, decode_none, lambda _: ())
|
|
163
|
+
BOOL = (2, bool, encode_bool, decode_bool, lambda _: ())
|
|
164
|
+
INT = (3, int, encode_int, decode_int, lambda _: ())
|
|
165
|
+
STRING = (4, str, encode_string, decode_string, lambda _: ())
|
|
166
|
+
BYTES = (5, bytes, encode_bytes, decode_bytes, lambda _: ())
|
|
167
|
+
LIST = (6, list, encode_list, decode_list, iter)
|
|
168
|
+
TUPLE = (7, tuple, encode_tuple, decode_tuple, iter)
|
|
169
|
+
DICT = (8, dict, encode_dict, decode_dict, lambda d: chain(d.keys(), d.values()))
|
|
170
|
+
SET = (9, set, encode_set, decode_set, iter)
|
|
171
|
+
FROZENSET = (10, frozenset, encode_frozenset, decode_frozenset, iter)
|
|
172
|
+
CUSTOM = (11, _CustomObject, encode_custom, decode_custom, lambda c: c.serialize())
|
|
173
|
+
|
|
174
|
+
def __init__(self, encoding_id, source_type, encoding_function, decoding_function, children):
|
|
175
|
+
self.encoding_id = encoding_id
|
|
176
|
+
self.source_type = source_type
|
|
177
|
+
self.encode = encoding_function
|
|
178
|
+
self.decode = decoding_function
|
|
179
|
+
self.children = children
|
|
180
|
+
ENCODINGS_BY_TYPE[self.source_type] = self
|
|
181
|
+
ENCODINGS_BY_ID[self.encoding_id] = self
|
|
182
|
+
|
|
183
|
+
@staticmethod
|
|
184
|
+
def get_by_type(source_type):
|
|
185
|
+
if source_type not in ENCODINGS_BY_TYPE:
|
|
186
|
+
return None
|
|
187
|
+
return ENCODINGS_BY_TYPE[source_type]
|
|
188
|
+
|
|
189
|
+
@staticmethod
|
|
190
|
+
def get_by_id(encoding_id):
|
|
191
|
+
if encoding_id not in ENCODINGS_BY_ID:
|
|
192
|
+
return None
|
|
193
|
+
return ENCODINGS_BY_ID[encoding_id]
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
class EncodingError(RuntimeError):
|
|
197
|
+
def __init__(self, *args):
|
|
198
|
+
super().__init__(*args)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def encode(obj, stream):
|
|
202
|
+
stack = [obj]
|
|
203
|
+
# Object ID 0 is reserved
|
|
204
|
+
obj_ids = {
|
|
205
|
+
0: None
|
|
206
|
+
}
|
|
207
|
+
objs = [
|
|
208
|
+
(None, None)
|
|
209
|
+
]
|
|
210
|
+
|
|
211
|
+
# Do a DFS traversal to assign IDs
|
|
212
|
+
while stack:
|
|
213
|
+
s = stack.pop()
|
|
214
|
+
encoding = EncodeTypes.get_by_type(type(s))
|
|
215
|
+
if encoding is None:
|
|
216
|
+
# See if there is a custom encoding:
|
|
217
|
+
if type(s) in CUSTOM_ENCODINGS:
|
|
218
|
+
encoding = EncodeTypes.CUSTOM
|
|
219
|
+
else:
|
|
220
|
+
raise EncodingError(f"No encoding implemented for objects of type {type(s)}")
|
|
221
|
+
already_expanded = id(s) in obj_ids
|
|
222
|
+
if already_expanded:
|
|
223
|
+
old_id = obj_ids[id(s)]
|
|
224
|
+
# We add one to new_id here because obj_id zero is reserved
|
|
225
|
+
new_id = len(objs)
|
|
226
|
+
obj_ids[id(s)] = new_id
|
|
227
|
+
objs.append((s, encoding))
|
|
228
|
+
if already_expanded:
|
|
229
|
+
objs[old_id] = (None, None)
|
|
230
|
+
# Remove all of the dependencies, since they now need to be added after:
|
|
231
|
+
# TODO: eventually do cycle detection here, and throw an error instead of livelock
|
|
232
|
+
for child in encoding.children(s):
|
|
233
|
+
if id(child) in obj_ids:
|
|
234
|
+
objs[obj_ids[id(child)]] = (None, None)
|
|
235
|
+
del obj_ids[id(child)]
|
|
236
|
+
stack.extend(encoding.children(s))
|
|
237
|
+
|
|
238
|
+
# write the objects to the stream in reverse
|
|
239
|
+
n = len(objs)
|
|
240
|
+
for i, (s, encoding) in enumerate(reversed(objs)):
|
|
241
|
+
obj_id = n - i - 1
|
|
242
|
+
if encoding is None:
|
|
243
|
+
# This object was referenced twice, and this was a duplicate
|
|
244
|
+
continue
|
|
245
|
+
write_int(obj_id, stream)
|
|
246
|
+
write_int(encoding.encoding_id, stream)
|
|
247
|
+
encoding.encode(s, obj_ids, stream)
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def decode(stream):
|
|
251
|
+
objs = {}
|
|
252
|
+
while True:
|
|
253
|
+
b = stream.read(1)
|
|
254
|
+
if b is None or not b:
|
|
255
|
+
break
|
|
256
|
+
stream.seek(-1, 1)
|
|
257
|
+
obj_id = read_int(stream)
|
|
258
|
+
assert obj_id not in objs
|
|
259
|
+
encoding_id = read_int(stream)
|
|
260
|
+
encoding = EncodeTypes.get_by_id(encoding_id)
|
|
261
|
+
if encoding is None:
|
|
262
|
+
raise EncodingError(f"Unexpected encoded object of type #{obj_id}")
|
|
263
|
+
objs[obj_id] = encoding.decode(objs, stream)
|
|
264
|
+
return objs[1]
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def dump(obj, stream):
|
|
268
|
+
return encode(obj, stream)
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def load(stream):
|
|
272
|
+
return decode(stream)
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def dumps(obj):
|
|
276
|
+
stream = io.BytesIO()
|
|
277
|
+
dump(obj, stream)
|
|
278
|
+
return stream.getvalue()
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def loads(string:bytes):
|
|
282
|
+
with io.BytesIO(string) as stream:
|
|
283
|
+
return load(stream)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
if __name__ == '__main__':
|
|
287
|
+
ref = ["list", "used", "twice"]
|
|
288
|
+
test_obj = {
|
|
289
|
+
'testing': {
|
|
290
|
+
'foo': {10},
|
|
291
|
+
'bar': [1, 2, 3, b'1234\xFF', True, False],
|
|
292
|
+
'ref': ref
|
|
293
|
+
},
|
|
294
|
+
'baz': [
|
|
295
|
+
'a', ('b',), 'c',
|
|
296
|
+
{'d': 5},
|
|
297
|
+
None,
|
|
298
|
+
frozenset([1, 1, 2, 3, 5, 8])
|
|
299
|
+
],
|
|
300
|
+
'ref': ref
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
#print(test_obj)
|
|
304
|
+
#encoded = encode(test_obj)
|
|
305
|
+
#print(encoded)
|
|
306
|
+
#decoded = decode(encoded)
|
|
307
|
+
#print(decoded)
|
|
308
|
+
|
|
309
|
+
for i in range(0, 2048):
|
|
310
|
+
assert loads(dumps(i)) == i
|
|
311
|
+
|
|
312
|
+
b = b"The quick brown fox jumps over the lazy dog"
|
|
313
|
+
s = b.decode('utf-8')
|
|
314
|
+
assert loads(dumps(b)) == b
|
|
315
|
+
assert loads(dumps(s)) == s
|
|
316
|
+
|
|
317
|
+
lst = list(range(1024))
|
|
318
|
+
assert loads(dumps(lst)) == lst
|
|
319
|
+
|
|
320
|
+
encoded = dumps(test_obj)
|
|
321
|
+
print(f"Encoded bytes: {len(encoded)}")
|
|
322
|
+
|
|
323
|
+
print(loads(encoded))
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from typing import Iterator, Optional
|
|
2
|
+
|
|
3
|
+
from .fileutils import Tempfile
|
|
4
|
+
from .polyfile import InvalidMatch, Match, Matcher, Submatch
|
|
5
|
+
from .structs import Field, Struct, StructError
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class PolyFileStruct(Struct):
|
|
9
|
+
__name__: Optional[str] = None
|
|
10
|
+
|
|
11
|
+
@property
|
|
12
|
+
def match_name(self) -> str:
|
|
13
|
+
if self.__name__ is not None:
|
|
14
|
+
return self.__name__
|
|
15
|
+
else:
|
|
16
|
+
return self.__class__.__name__
|
|
17
|
+
|
|
18
|
+
def match(self, matcher: Matcher, parent: Optional[Match] = None) -> Iterator[Submatch]:
|
|
19
|
+
m = Submatch(
|
|
20
|
+
self.match_name,
|
|
21
|
+
match_obj=self,
|
|
22
|
+
relative_offset=self.start_offset,
|
|
23
|
+
length=self.num_bytes,
|
|
24
|
+
parent=parent,
|
|
25
|
+
matcher=matcher
|
|
26
|
+
)
|
|
27
|
+
yield m
|
|
28
|
+
for field_name in self.fields.keys():
|
|
29
|
+
value: Field = getattr(self, field_name)
|
|
30
|
+
s = Submatch(
|
|
31
|
+
field_name,
|
|
32
|
+
match_obj=value,
|
|
33
|
+
relative_offset=value.start_offset - self.start_offset,
|
|
34
|
+
length=value.num_bytes,
|
|
35
|
+
parent=m,
|
|
36
|
+
matcher=matcher
|
|
37
|
+
)
|
|
38
|
+
yield s
|
|
39
|
+
try:
|
|
40
|
+
if isinstance(value, PolyFileStruct):
|
|
41
|
+
yield from value.match(matcher, s)
|
|
42
|
+
elif isinstance(value, bytes):
|
|
43
|
+
with Tempfile(value) as tmp:
|
|
44
|
+
yield from matcher.match(tmp, parent=s)
|
|
45
|
+
except (InvalidMatch, StructError):
|
|
46
|
+
pass
|