{"id":51176206,"url":"https://github.com/ne0ekspert/libxgwx","last_synced_at":"2026-06-27T04:02:24.075Z","repository":{"id":357998103,"uuid":"1224250856","full_name":"ne0ekspert/libxgwx","owner":"ne0ekspert","description":"Rust parser for LS XG5000 .xgwx workspace files","archived":false,"fork":false,"pushed_at":"2026-06-15T06:38:43.000Z","size":221,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-15T08:21:56.785Z","etag":null,"topics":["parser","parser-library","plc"],"latest_commit_sha":null,"homepage":"https://ne0ekspert.github.io/libxgwx/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ne0ekspert.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-29T05:20:20.000Z","updated_at":"2026-06-15T06:38:48.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ne0ekspert/libxgwx","commit_stats":null,"previous_names":["ne0ekspert/libxgwx"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ne0ekspert/libxgwx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ne0ekspert%2Flibxgwx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ne0ekspert%2Flibxgwx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ne0ekspert%2Flibxgwx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ne0ekspert%2Flibxgwx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ne0ekspert","download_url":"https://codeload.github.com/ne0ekspert/libxgwx/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ne0ekspert%2Flibxgwx/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34840899,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-27T02:00:06.362Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["parser","parser-library","plc"],"created_at":"2026-06-27T04:02:20.141Z","updated_at":"2026-06-27T04:02:24.065Z","avatar_url":"https://github.com/ne0ekspert.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# libxgwx\n\nRust parser for LS XG5000 `.xgwx` workspace files.\n\nThe parser handles the container layout observed in LS XG5000 workspace files:\n\n- `XG` binary workspace header\n- gzip-compressed UTF-8 XML project payload\n- optional trailing binary metadata\n\nUnknown binary sections are preserved so callers can inspect them later.\n\n## Usage\n\n```rust\nuse xgwx::XgwxDocument;\n\nlet doc = XgwxDocument::from_path(\"project.xgwx\")?;\nlet project = doc.project_info();\n\nprintln!(\"header label: {:?}\", doc.header.label);\nprintln!(\"project name: {:?}\", project.name);\nprintln!(\"file version: {:?}\", project.file_version);\n\nfor module in doc.modules() {\n    println!(\n        \"module base={:?} slot={:?} id={:?} name={:?}\",\n        module.base,\n        module.slot,\n        module.id,\n        module.name\n    );\n}\n\nfor program in doc.programs() {\n    println!(\"program: {:?}\", program.name);\n}\n\n# Ok::\u003c(), Box\u003cdyn std::error::Error\u003e\u003e(())\n```\n\n## API\n\n- `XgwxDocument::parse(\u0026[u8])` parses from bytes.\n- `XgwxDocument::from_path(...)` parses from a file.\n- `XgwxDocument::project_info()` returns root project metadata.\n- `XgwxDocument::configurations()`, `networks()`, `network_modules()`, `bases()`,\n  `modules()`, `tasks()`, `programs()`, `high_speed_links()`, and\n  `high_speed_link_blocks()` return owned high-level summaries.\n- `XgwxDocument::variables()` decodes the compressed global symbol table into\n  variable summaries with name, formatted address, memory area, address number,\n  data type, description, source reference, and range.\n- `XgwxDocument::ladder_programs()` partially decodes base64/bzip2 ladder\n  `ProgramData`, preserving raw bytes and extracting embedded strings and likely\n  ladder elements such as instruction calls, comparisons, timers, logic\n  operators, device references, constants, comments, and internal references.\n- `ladder_mnemonic_info(...)` and `known_ladder_mnemonics()` expose category\n  and description metadata for known ladder instruction mnemonics.\n- `XgwxDocument::project_options()`, `parameters()`, `hsc_parameters()`,\n  `safety_comm()`, `trend_monitoring()`, `xgpd_config_infos()`,\n  `cnet_config_infos()`, `fenet_config_infos()`, and `properties()` expose\n  other high-level project sections found in the XML.\n- `XgwxDocument::position_parameters()` exposes X/Y position-control axis\n  parameters and step tables from `POSITION PARAMETER` sections.\n- `XgwxDocument::pid_cal_parameters()` and\n  `XgwxDocument::pid_tune_parameters()` expose embedded PID loop calculation and\n  tuning settings.\n- `XgwxDocument::cnet_config_infos()` exposes Cnet module and serial port\n  settings. It preserves raw values and decodes known enums:\n  `Mode` (`0` = RS232C, `1` = RS422, `2` = RS485), `DataBit`\n  (`0` = 7 bits, `1` = 8 bits), `StopBit` (`0` = 1, `1` = 2), and\n  `Parity` (`0` = NONE, `1` = EVEN, `2` = ODD). `Bps` is also exposed as a\n  decoded baud rate using `Bps * 1200`.\n- Cnet DI/DO/AI/AO device areas are decoded from ASCII numeric device codes.\n  DI/DO addresses are formatted as bit addresses with LSD hex notation, while\n  AI/AO addresses are formatted as decimal word addresses.\n- `XgwxDocument::fenet_config_infos()` exposes FEnet module IPv4 settings such\n  as IP address, subnet, gateway, and DNS.\n- `XgwxDocument::hsc_parameters()` decodes XGB `HSC PARAMETER` `PAYLOAD`\n  attributes, preserving raw bytes and exposing the known per-channel counter\n  mode (`0` = Linear Counter, `1` = Ring Counter) and pulse input mode\n  (`0` = 1-Phase 1-Input 1x, `1` = 1-Phase 2-Input 1x, `2` = CW/CCW,\n  `3` = 2-Phase 4x), plus compare output mode, internal/external preset byte\n  fields, ring counter maximum, compare output minimum, compare output maximum,\n  unit time in milliseconds, and pulses per revolution values. Compare output\n  modes map `0..=6` to Less Than, Less Or Equal, Equal, Greater Or Equal,\n  Greater Than, Includes, and Excludes.\n- `XgwxDocument::decoded_payloads()` returns an inventory of base64 binary\n  payloads with XML path, compression flag, encoded length, raw length, decoded\n  length, attributes, and decoded bytes.\n- `XgwxDocument::xml` contains the inflated XML payload.\n- `XgwxDocument::root` contains a lightweight owned XML tree.\n- `XgwxDocument::trailer` contains raw bytes after the main XML payload.\n- `XgwxDocument::trailer_gzip_members` contains any valid gzip members found in the trailer.\n\n## TUI PoC\n\nRun the included example against a local workspace file:\n\n```sh\ncargo run --example tui -- path/to/project.xgwx\n```\n\nUse `j`/`k` or arrow keys to move through programs, and `q` or `Esc` to quit.\nUse `Tab` to switch between program structure, network, variable, parameter,\nand data views. Use `PageUp`/`PageDown` to scroll the right detail panel.\n\nThe TUI detail panels intentionally render complete details and rely on\nscrolling instead of hiding entries behind `... more` counters. In the\nParameters view, `BASIC PARAMETER` attributes with numeric suffixes such as\n`KEY_0`, `KEY_1`, and `KEY_2` are grouped under `KEY` with indented index rows.\n\nThe Networks view joins parsed Cnet and FEnet configuration records back to\nnetwork modules by stable module type only: `NetworkModule Id` equals\n`XGPD_CONFIG_INFO_* Type`. It does not use base or slot for that association,\nbecause those fields can be changed by users in XG5000 projects.\n\n## Inspect Example\n\nRun the non-interactive inspector for a concise text summary:\n\n```sh\ncargo run --example inspect -- fixtures/XGB_Enet01.xgwx\n```\n\nThis prints project counts plus decoded Cnet, FEnet, HSC, position, and PID\nsummaries. It is useful for comparing parser output across fixture files without\nopening the TUI.\n\n## Benchmark Example\n\nRun the fixture-backed benchmark in release mode:\n\n```sh\ncargo run --release --example bench -- --warmup 50 --iterations 500 fixtures\n```\n\nThe benchmark reads `.xgwx` fixture bytes once, then measures parser-only work\nand parser plus higher-level decoding paths such as variables, ladder programs,\nparameters, network summaries, and decoded payloads.\n\n## GUI Ladder PoC\n\nRun the graphical ladder viewer:\n\n```sh\ncargo run --features gui --example gui -- path/to/project.xgwx\n```\n\nThe GUI lists decoded ladder programs on the left and renders the selected\nprogram as a scrollable, zoomable ladder canvas using parsed rungs, cells, and\nwire segments.\n\n## WebAssembly Demo\n\nThe parser can be compiled for browser use through the optional `wasm` feature.\nThe browser-facing API accepts bytes, so users can parse files selected from a\nlocal file picker without uploading them anywhere.\n\n```sh\ncargo check --target wasm32-unknown-unknown --features wasm\nwasm-pack build --target web --out-dir web/dist/pkg --out-name libxgwx --features wasm --no-default-features\ncp web/index.html web/styles.css web/app.js web/dist/\n```\n\nThe GitHub Pages workflow builds the same upload-only demo from `web/`. It does\nnot publish `.xgwx` fixtures into the Pages artifact. The demo shows project\nsummaries, a program sidebar, decoded variables, hardware modules, decoded\nnetwork and parameter summaries, and a best-effort SVG ladder viewer for\ndecoded ladder programs.\n\n## Fixtures\n\nThe repository includes small `.xgwx` files in `fixtures/` for the normal test\nsuite. They are included with the original author's permission for parser\ndevelopment and testing; see `fixtures/README.md` for attribution and\npermission details.\n\nTo run an additional smoke test against another real workspace, keep that file\noutside the commit and pass it with an environment variable:\n\n```sh\nLIBXGWX_FIXTURE=path/to/project.xgwx cargo test parses_real_fixture_from_env -- --ignored\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fne0ekspert%2Flibxgwx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fne0ekspert%2Flibxgwx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fne0ekspert%2Flibxgwx/lists"}