ecma335 v1.0.0
ecma335
ECMA 335 Parser
Installation
-
Add the dependency to your
shard.yml:dependencies: ecma335: github: mjblack/ecma335 -
Run
shards install
Usage
require "ecma335"
parsed = Ecma335.parse("winmd/Windows.Win32.winmd")
puts "Metadata version: #{parsed.metadata_root.version_string}"
parsed.metadata_root.streams.each do |stream|
puts "#{stream.name}: offset=0x#{stream.offset.to_s(16)} size=#{stream.size}"
end
if tables = parsed.metadata_root.tables_stream
puts "TypeDef rows: #{tables.row_count("TypeDef")}"
puts "MethodDef rows: #{tables.row_count("MethodDef")}"
puts "coverage: #{(tables.parse_coverage_ratio * 100).round(2)}%"
p tables.skipped_tables
tables.type_defs.first(5).each do |row|
puts "TypeDef: #{row.type_namespace}.#{row.type_name}"
end
tables.method_defs.first(5).each do |row|
puts "MethodDef: #{row.name} (rva=0x#{row.rva.to_s(16)})"
if sig = row.decoded_signature
params = sig.parameter_types.join(", ")
puts " signature: (#{params}) -> #{sig.return_type}"
puts " canonical: #{sig.to_signature_string(canonical: true)}"
end
end
end
Consumer API
This library is parser-focused. It does not generate Crystal bindings directly.
Ecma335.parse also builds a normalized API model suitable for a separate generator app:
parsed = Ecma335.parse("winmd/Windows.Win32.winmd")
api = parsed.api_model
if api
type = api.type?("Windows.Win32.Foundation.HRESULT")
p type.try(&.methods.size)
p type.try(&.token)
p type.try(&.generic_params)
namespace_types = api.types_in_namespace("Windows.Win32.Foundation")
puts "types in namespace: #{namespace_types.size}"
method = api.method?("Windows.Win32.Foundation.HRESULT", "SomeMethod")
p method.try(&.native_import)
p method.try(&.token)
p method.try(&.generic_params)
end
# Token-based metadata row helpers (TypeDef/MethodDef/Field)
p parsed.type_def_by_token?(0x02000001_u32).try(&.type_name)
p parsed.method_def_by_token?(0x06000001_u32).try(&.name)
p parsed.field_by_token?(0x04000001_u32).try(&.name)
# Optional strict mode: raise when parser has to skip undecoded tables.
strict_parsed = Ecma335.parse("winmd/Windows.Win32.winmd", strict: true)
Development
Run tests:
crystal spec
Fetch Windows.Win32.winmd (uses the version pinned in winmd.version):
pwsh ./scripts/fetch-winmd.ps1
Override the version or output path:
pwsh ./scripts/fetch-winmd.ps1 -Version 70.0.11-preview
pwsh ./scripts/fetch-winmd.ps1 -OutputPath winmd/Windows.Win32.winmd
WinMD Utility
This repo includes a small CLI utility for inspecting WinMD files:
crystal run src/ecma335_tool.cr -- winmd/Windows.Win32.winmd stats
crystal run src/ecma335_tool.cr -- winmd/Windows.Win32.winmd list types --limit 20
crystal run src/ecma335_tool.cr -- winmd/Windows.Win32.winmd list types --namespace Windows.Win32.UI.Controls
crystal run src/ecma335_tool.cr -- winmd/Windows.Win32.winmd list methods --type Windows.Win32.Foundation.HRESULT --limit 20
crystal run src/ecma335_tool.cr -- winmd/Windows.Win32.winmd list methods --all
crystal run src/ecma335_tool.cr -- winmd/Windows.Win32.winmd show type Windows.Win32.Foundation.HRESULT
crystal run src/ecma335_tool.cr -- winmd/Windows.Win32.winmd show method Windows.Win32.Foundation.HRESULT#SomeMethod
crystal run src/ecma335_tool.cr -- winmd/Windows.Win32.winmd show type Windows.Win32.Foundation.HRESULT --json
crystal run src/ecma335_tool.cr -- --json winmd/Windows.Win32.winmd stats
crystal run src/ecma335_tool.cr -- --json winmd/Windows.Win32.winmd list methods --limit 20
crystal run src/ecma335_tool.cr -- --json winmd/Windows.Win32.winmd search CreateFile --methods
crystal run src/ecma335_tool.cr -- winmd/Windows.Win32.winmd search CreateFile --methods --limit 20
crystal run src/ecma335_tool.cr -- winmd/Windows.Win32.winmd search CreateFile --methods --all
Notes:
list typeshides special metadata entries like<Module>by default.list typesin text mode shows nested types as dotted paths (for exampleParentType._Anonymous_e__Union).- Use
--include-specialto include those entries. --namespaceexpects a namespace (for exampleWindows.Win32.UI.Controls), but if you pass an exact full type name it will still return that direct match.listandsearchdefault to--limit 50; use--allfor uncapped output.
Or build and run the shard target:
shards build ecma335-tool
./bin/ecma335-tool winmd/Windows.Win32.winmd stats
Integration test behavior:
spec/ecma335_spec.crincludes an integration example forwinmd/Windows.Win32.winmd.- If that file exists, the integration example runs by default.
- If the file is missing, that single integration example is marked pending with a helpful message.
Contributing
- Fork it (https://github.com/mjblack/ecma335/fork)
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create a new Pull Request
Contributors
- Matthew J. Black - creator and maintainer
Repository
ecma335
Owner
Statistic
- 0
- 0
- 0
- 0
- 0
- about 5 hours ago
- June 10, 2026
License
MIT License
Links
Synced at
Thu, 11 Jun 2026 01:21:39 GMT
Languages