metar_taf_parser
⚠️ Status: Active development – current version
0.4.6
A modern, strongly-typed METAR and TAF parser library written in Rust.
This project is now focused on the single library crate (metar-taf-parser) and is a
Rust port of the original Python project:
https://github.com/mivek/python-metar-taf-parser
Porting and parity work also tracks the maintained fork: https://github.com/umpire274/python-metar-taf-parser.
✈️ Goals
- Provide a robust Rust-native API for METAR/TAF parsing.
- Reach feature parity with the referenced Python fork.
- Keep the public API ergonomic and strongly typed for embedding in other apps.
- During porting, parser groups are being migrated using the same regex-first approach used in the Python fork to preserve behavior.
- Porting process follows a regex-alignment policy documented in
docs/PORTING_REGEX_POLICY.md.
🧱 Architecture
The repository now exposes a single library crate at the root:
metar_taf_parser/
├── src/
├── tests/
├── resources/
├── Cargo.toml
├── README.md
└── CHANGELOG.md
Core library (metar-taf-parser)
- Token-based parsing
- Strongly typed domain models
- Designed to be embedded in other applications
- No CLI assumptions
📚 Library usage
Add the core crate to your Cargo.toml:
[]
= "0.4.6"
Unified entry-point
When the report type is not known in advance, use parse to let the library
select the correct decoder automatically:
use ;
let report = parse?;
// or
let report = parse?;
match report
parse_strict behaves the same but requires an explicit METAR, SPECI, or
TAF prefix and rejects unrecognised groups:
use ;
// no prefix → error
assert!;
use parse_metar;
let metar = parse_metar?;
assert_eq!;
assert!;
assert!;
TAF example (tolerant mode)
use parse_taf;
let taf = parse_taf?;
assert_eq!;
assert!;
// In tolerant mode, unsupported tokens are preserved in `unparsed_groups`.
METAR strict mode example
use parse_metar_strict;
let strict_result = parse_metar_strict;
assert!;
TAF strict mode example
use parse_taf_strict;
let strict_result = parse_taf_strict;
assert!;
Natural language description — field access (METAR)
Use describe_metar when you need to inspect individual fields programmatically.
use ;
let metar = parse_metar?;
let desc = describe_metar;
println!;
// "wind from 180° at 10 kt"
println!;
// "visibility greater than 10 km"
println!;
// "few clouds at 3000 ft"
println!;
// "temperature 18°C, dew point 12°C"
println!;
// "QNH 1015 hPa"
Natural language description — full formatted output (METAR)
Use format_metar (or println!("{}", desc)) to print the complete report in one call.
Only the fields actually present in the message are included.
use ;
let metar = parse_metar?;
println!;
METAR LIRF
Time: Day 12 at 12:50Z
Wind: wind from 180° at 10 kt
Visibility: visibility greater than 10 km
Weather: light rain
Clouds: few clouds at 3000 ft
Temperature: temperature 18°C, dew point 12°C
Pressure: QNH 1015 hPa
Trend: no significant change
Natural language description — field access (TAF)
use ;
let taf = parse_taf?;
let desc = describe_taf;
println!;
// "12/12Z to 13/18Z"
for forecast in &desc.forecasts
// [Base forecast]
// wind from 180° at 10 kt
// visibility greater than 10 km
// scattered clouds at 2000 ft
// [Temporary]
// visibility 4000 m
// light rain
Natural language description — full formatted output (TAF)
use ;
let taf = parse_taf?;
println!;
TAF LIRF
Issued: Day 12 at 11:00Z
Validity: 12/12Z to 13/18Z
[Base forecast]
Wind: wind from 180° at 10 kt
Visibility: visibility greater than 10 km
Clouds: scattered clouds at 2000 ft
Max temp: maximum temperature 18°C on day 12 at 14:00Z
Min temp: minimum temperature 8°C on day 13 at 04:00Z
[Temporary] 12/18Z to 12/22Z
Visibility: visibility 4000 m
Weather: light rain
Structured METAR remarks (RMK section)
The RMK section is parsed into typed variants instead of a raw string.
Access the raw text via remarks.raw; inspect parsed groups via remarks.items.
use parse_metar;
use ;
let metar = parse_metar?;
for remark in &metar.remarks.items
// Raw text is always preserved:
assert_eq!;
// Unrecognised tokens end up in remarks.unparsed:
let m2 = parse_metar?;
assert_eq!;
Recognised remark variants: PeakWind, WindShift, SeaLevelPressure,
PrecipitationAmount, HourlyTemperature, MaxMinTemperature, PressureTendency,
AutoStation, Lightning, Virga, MaintenanceIndicator,
PressureRisingRapidly, PressureFallingRapidly, SensorStatus.
The nosig field on Metar is true whenever a NOSIG trend group is present.
Wind direction variation (METAR)
When a variable direction range follows the wind group, it is stored in wind.variation:
use parse_metar;
let m = parse_metar?;
let v = m.wind.unwrap.variation.unwrap;
assert_eq!;
assert_eq!;
Icing and turbulence in TAF forecasts
Icing (6ABBBC) and turbulence (5ABBBC) groups are parsed into typed vectors on each
TafForecast block:
use parse_taf;
use IcingIntensity;
use TurbulenceIntensity;
let taf = parse_taf?;
let fc = &taf.forecasts;
// Icing: 6 + intensity=1(Light) + base=030(3000 ft) + thickness=4(4000 ft)
assert_eq!;
assert_eq!;
// Turbulence: 5 + intensity=2(ModerateInCloud) + base=080(8000 ft) + thickness=3(3000 ft)
assert_eq!;
assert_eq!;
SPECI (special observation)
The parser recognises SPECI as an optional leading token alongside METAR.
The report type is stored in metar.report_type and reflected in MetarDescription::report_type.
use parse_metar;
use MetarReportType;
let m = parse_metar?;
assert_eq!;
Military color code (NATO/UK MIL-METAR)
Military airfield METARs carry a NATO color state (BLU, WHT, GRN, YLO, AMB, RED).
A BLACK variant (BLU+, etc.) indicates the field is closed for that state.
A second bare color code token is treated as the implicit BECMG forecast state.
use parse_metar;
use ;
let m = parse_metar?;
assert_eq!;
assert_eq!;
Sea state (offshore stations)
Offshore and ship stations report water temperature and wave state using W<TT>/S<n> or
W<TT>/H<hh> tokens. The optional M prefix encodes negative temperatures.
use parse_metar;
use WaveHeightKind;
let m = parse_metar?;
let ss = m.sea_state.unwrap;
assert_eq!;
assert_eq!;
assert_eq!;
Wind shear on runways (METAR)
The WS R<rwy> and WS ALL RWY groups are parsed into a typed Vec on the Metar struct.
use parse_metar;
use MetarWindShearRunway;
let m = parse_metar?;
assert_eq!;
let m2 = parse_metar?;
assert_eq!;
Typical parser use cases
- Parse a single METAR and inspect typed fields (
wind,visibility,clouds,temperature,pressure). - Parse a TAF and iterate forecast sections (
BASE,FM,BECMG,TEMPO,PROB). - Enable strict TAF mode in validation pipelines where unknown groups must fail fast.
- Use tolerant mode when you want best-effort parsing plus visibility on unsupported tokens.
📘 Documentation
- Porting policy:
docs/PORTING_REGEX_POLICY.md - Full codebase reference (modules, structs, enums, functions):
docs/CODEBASE_REFERENCE.md
🧪 Testing
📄 License
MIT License.