use std::fmt;
use crate::types::{
CloudLayer, Clouds, Data, Time, VertVisibility, Visibility, Weather, WeatherCondition, Wind,
};
use types::{
MetarType, Pressure, Rvr, RvrChange, RvrDistance, RvrModifier, Sea, Trend, TrendData,
TrendType, WindShear,
};
pub mod parser;
pub mod types;
#[derive(PartialEq, Clone, Debug)]
pub struct Metar {
pub report_type: MetarType,
pub is_corrected: bool,
pub station: String,
pub time: Time,
pub is_auto: bool,
pub is_nil: bool,
pub wind: Wind,
pub visibility: Data<Visibility>,
pub rvr: Vec<Rvr>,
pub clouds: Data<Clouds>,
pub cloud_layers: Vec<CloudLayer>,
pub vert_visibility: Option<VertVisibility>,
pub weather: Vec<Weather>,
pub temperature: Data<i32>,
pub dewpoint: Data<i32>,
pub pressure: Data<Pressure>,
pub recent: Vec<Data<WeatherCondition>>,
pub wind_shear: Vec<WindShear>,
pub sea: Option<Sea>,
pub remarks: Option<String>,
pub trend: Vec<Trend>,
}
impl Metar {
pub fn parse<S>(data: S) -> Result<Self, MetarError>
where
S: Into<String>,
{
parser::parse(data.into())
}
}
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct MetarError {
pub string: String,
pub start: usize,
pub length: usize,
pub variant: pest::error::ErrorVariant<parser::Rule>,
}
impl std::error::Error for MetarError {}
impl fmt::Display for MetarError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut caret = String::new();
for _ in 0..self.start {
caret.push(' ');
}
caret.push('^');
for _ in 1..self.length {
caret.push('~');
}
writeln!(f, "{}\n{}\n{:?}", self.string, caret, self.variant)
}
}
#[cfg(test)]
mod tests {
use crate::metar::types::Pressure::Hectopascals;
use crate::metar::types::RvrChange::{Decreased, Unchanged};
use crate::metar::{Metar, MetarError, MetarType, RvrDistance, RvrModifier};
use crate::types::CloudLayer::{Broken, Few, Overcast, Scattered};
use crate::types::CloudType::Normal;
use crate::types::Clouds::{CloudLayers, NoCloudDetected};
use crate::types::Data::Known;
use crate::types::Visibility;
use crate::types::Visibility::Metres;
use crate::types::WeatherCondition::{Blowing, Drizzle, Fog, Rain, Showers, Snow};
use crate::types::WeatherIntensity::{Light, Moderate};
use crate::types::WindDirection::{Heading, Variable};
use crate::types::WindSpeed::{Knot, MetresPerSecond};
use reqwest::blocking::Client;
use std::fs::read_to_string;
static URL: &str = "https://aviationweather.gov/api/data/metar?ids=";
#[test]
fn test_metar_file() {
let mut counter: u64 = 1;
let mut failed: bool = false;
for line in read_to_string("test/resources/metar.txt").unwrap().lines() {
let result = Metar::parse(line);
if result.is_err() {
let error = result.err().unwrap();
println!("--------------------------------------------");
println!("--------------------------------------------");
println!("Error on line: {}", counter);
println!("Input: {}", error.string);
println!("Start: {}", error.start);
println!("Length: {}", error.length);
println!("Error message: {}", error.variant);
println!("Error part: {}", error.string.get(error.start..).unwrap());
println!("--------------------------------------------");
println!("--------------------------------------------");
failed = true;
}
counter = counter + 1;
}
if failed == true {
panic!()
}
}
#[test]
fn test_metar_file2() {
let mut counter: u64 = 1;
let mut failed: bool = false;
for line in read_to_string("test/resources/metar2.txt").unwrap().lines() {
let result = Metar::parse(line);
if result.is_err() {
let error = result.err().unwrap();
println!("Error in line {}: {}", counter, line);
println!("--------------------------------------------");
println!("--------------------------------------------");
println!("Input: {}", error.string);
println!("Start: {}", error.start);
println!("Length: {}", error.length);
println!("Error message: {}", error.variant);
println!("Error part: {}", error.string.get(error.start..).unwrap());
println!("--------------------------------------------");
println!("--------------------------------------------");
failed = true;
}
counter = counter + 1;
}
if failed == true {
panic!()
}
}
#[test]
fn test_metar_file3() {
let mut counter: u64 = 1;
let mut failed: bool = false;
for line in read_to_string("test/resources/metar3.txt").unwrap().lines() {
let result = Metar::parse(line);
if result.is_err() {
let error = result.err().unwrap();
println!("Error in line {}: {}", counter, line);
println!("--------------------------------------------");
println!("--------------------------------------------");
println!("Input: {}", error.string);
println!("Start: {}", error.start);
println!("Length: {}", error.length);
println!("Error message: {}", error.variant);
println!("Error part: {}", error.string.get(error.start..).unwrap());
println!("--------------------------------------------");
println!("--------------------------------------------");
failed = true;
}
counter = counter + 1;
}
if failed == true {
panic!()
}
}
#[test]
fn test_metar_0() {
let metar =
"EGHI 282120Z 19015G32KT 140V220 6000 RA SCT006 BKN009 16/14 Q1006 RMK EXAMPLE METAR=";
let result = Metar::parse(metar);
evaluate_result(result.clone());
assert!(result.is_ok());
let result_metar = result.unwrap();
assert_eq!(MetarType::Metar, result_metar.report_type);
assert!(!result_metar.is_corrected);
assert_eq!("EGHI", result_metar.station);
assert!(!result_metar.is_auto);
assert!(!result_metar.is_nil);
assert_eq!(28u8, result_metar.time.date);
assert_eq!(21u8, result_metar.time.hour);
assert_eq!(20u8, result_metar.time.minute);
assert_eq!(Heading(190), result_metar.wind.dir.unwrap().clone());
assert_eq!(Knot(15), result_metar.wind.speed.unwrap().clone());
assert_eq!((Known(140), Known(220)), result_metar.wind.varying.unwrap());
assert_eq!(Knot(32), result_metar.wind.gusting.unwrap());
assert_eq!(Metres(6000), result_metar.visibility.unwrap().clone());
assert!(result_metar.rvr.is_empty());
assert_eq!(CloudLayers, result_metar.clouds.unwrap().clone());
assert_eq!(
Scattered(Normal, Some(6)),
result_metar.cloud_layers.first().unwrap().clone()
);
assert_eq!(
Broken(Normal, Some(9)),
result_metar.cloud_layers.get(1).unwrap().clone()
);
assert!(result_metar.vert_visibility.is_none());
assert_eq!(Moderate, result_metar.weather.first().unwrap().intensity);
assert_eq!(
Rain,
result_metar
.weather
.first()
.unwrap()
.conditions
.first()
.unwrap()
.clone()
);
assert_eq!(16i32, *result_metar.temperature.unwrap());
assert_eq!(14i32, *result_metar.dewpoint.unwrap());
assert_eq!(Hectopascals(1006), result_metar.pressure.unwrap().clone());
assert!(result_metar.recent.is_empty());
assert_eq!("RMK EXAMPLE METAR", result_metar.remarks.unwrap());
}
#[test]
fn test_metar_1() {
let metar =
"METAR EDDF 081650Z AUTO 20013KT 7000 -DZ BKN019 BKN028 OVC034 11/10 Q0996 NOSIG";
let result = Metar::parse(metar);
evaluate_result(result.clone());
assert!(result.is_ok());
let result_metar = result.unwrap();
assert_eq!(MetarType::Metar, result_metar.report_type);
assert!(!result_metar.is_corrected);
assert_eq!("EDDF", result_metar.station);
assert!(result_metar.is_auto);
assert!(!result_metar.is_nil);
assert_eq!(8u8, result_metar.time.date);
assert_eq!(16u8, result_metar.time.hour);
assert_eq!(50u8, result_metar.time.minute);
assert_eq!(Heading(200), result_metar.wind.dir.unwrap().clone());
assert_eq!(Knot(13), result_metar.wind.speed.unwrap().clone());
assert!(result_metar.wind.varying.is_none());
assert!(result_metar.wind.gusting.is_none());
assert_eq!(Metres(7000), result_metar.visibility.unwrap().clone());
assert!(result_metar.rvr.is_empty());
assert_eq!(CloudLayers, result_metar.clouds.unwrap().clone());
assert_eq!(
Broken(Normal, Some(19)),
result_metar.cloud_layers.first().unwrap().clone()
);
assert_eq!(
Broken(Normal, Some(28)),
result_metar.cloud_layers.get(1).unwrap().clone()
);
assert_eq!(
Overcast(Normal, Some(34)),
result_metar.cloud_layers.get(2).unwrap().clone()
);
assert!(result_metar.vert_visibility.is_none());
assert_eq!(Light, result_metar.weather.first().unwrap().intensity);
assert_eq!(
Drizzle,
result_metar
.weather
.first()
.unwrap()
.conditions
.first()
.unwrap()
.clone()
);
assert_eq!(11i32, *result_metar.temperature.unwrap());
assert_eq!(10i32, *result_metar.dewpoint.unwrap());
assert_eq!(Hectopascals(996), result_metar.pressure.unwrap().clone());
assert!(result_metar.recent.is_empty());
assert!(result_metar.remarks.is_none());
}
#[test]
fn test_metar_2() {
let metar = "METAR EDDH 081650Z AUTO 16010KT 9999 FEW045 03/00 Q0998 TEMPO 4500 -RASN";
let result = Metar::parse(metar);
evaluate_result(result.clone());
assert!(result.is_ok());
let result_metar = result.unwrap();
assert_eq!(MetarType::Metar, result_metar.report_type);
assert!(!result_metar.is_corrected);
assert_eq!("EDDH", result_metar.station);
assert!(result_metar.is_auto);
assert!(!result_metar.is_nil);
assert_eq!(8u8, result_metar.time.date);
assert_eq!(16u8, result_metar.time.hour);
assert_eq!(50u8, result_metar.time.minute);
assert_eq!(Heading(160), result_metar.wind.dir.unwrap().clone());
assert_eq!(Knot(10), result_metar.wind.speed.unwrap().clone());
assert!(result_metar.wind.varying.is_none());
assert!(result_metar.wind.gusting.is_none());
assert_eq!(Metres(9999), result_metar.visibility.unwrap().clone());
assert_eq!(CloudLayers, result_metar.clouds.unwrap().clone());
assert_eq!(
Few(Normal, Some(45)),
result_metar.cloud_layers.first().unwrap().clone()
);
assert!(result_metar.vert_visibility.is_none());
assert!(result_metar.weather.is_empty());
assert_eq!(3i32, *result_metar.temperature.unwrap());
assert_eq!(0i32, *result_metar.dewpoint.unwrap());
assert_eq!(Hectopascals(998), result_metar.pressure.unwrap().clone());
assert!(result_metar.recent.is_empty());
assert!(result_metar.remarks.is_none());
}
#[test]
fn test_metar_3() {
let metar = "METAR UEEE 081630Z 31001MPS 0500 0200SW R23L/1200N R23R/1000D FG NSC M41/M45 Q1024 R23/490147 NOSIG RMK QFE759";
let result = Metar::parse(metar);
evaluate_result(result.clone());
assert!(result.is_ok());
let result_metar = result.unwrap();
assert_eq!(MetarType::Metar, result_metar.report_type);
assert!(!result_metar.is_corrected);
assert_eq!("UEEE", result_metar.station);
assert!(!result_metar.is_auto);
assert!(!result_metar.is_nil);
assert_eq!(8u8, result_metar.time.date);
assert_eq!(16u8, result_metar.time.hour);
assert_eq!(30u8, result_metar.time.minute);
assert_eq!(Heading(310), result_metar.wind.dir.unwrap().clone());
assert_eq!(MetresPerSecond(1), result_metar.wind.speed.unwrap().clone());
assert!(result_metar.wind.varying.is_none());
assert!(result_metar.wind.gusting.is_none());
assert_eq!(Metres(500), result_metar.visibility.unwrap().clone());
assert!(!result_metar.rvr.is_empty());
assert_eq!("23L", result_metar.rvr.first().unwrap().runway);
assert_eq!(
Known(RvrDistance::Metres(1200u16)),
result_metar.rvr.first().unwrap().distance_low
);
assert_eq!(Unchanged, result_metar.rvr.first().unwrap().change);
assert_eq!(
RvrModifier::None,
result_metar.rvr.first().unwrap().modifier
);
assert_eq!("23R", result_metar.rvr.get(1).unwrap().runway);
assert_eq!(
Known(RvrDistance::Metres(1000u16)),
result_metar.rvr.get(1).unwrap().distance_low
);
assert_eq!(Decreased, result_metar.rvr.get(1).unwrap().change);
assert_eq!(RvrModifier::None, result_metar.rvr.get(1).unwrap().modifier);
assert_eq!(NoCloudDetected, result_metar.clouds.unwrap().clone());
assert!(result_metar.vert_visibility.is_none());
assert_eq!(1, result_metar.weather.len());
assert_eq!(Moderate, result_metar.weather.first().unwrap().intensity);
assert_eq!(1, result_metar.weather.first().unwrap().conditions.len());
assert_eq!(
Fog,
result_metar
.weather
.first()
.unwrap()
.conditions
.first()
.unwrap()
.clone()
);
assert_eq!(-41i32, *result_metar.temperature.unwrap());
assert_eq!(-45i32, *result_metar.dewpoint.unwrap());
assert_eq!(Hectopascals(1024), result_metar.pressure.unwrap().clone());
assert!(result_metar.recent.is_empty());
assert!(result_metar.remarks.is_some());
assert_eq!("RMK QFE759", result_metar.remarks.unwrap());
}
#[test]
fn test_metar_4() {
let metar = "METAR UEEE 081630Z 31001MPS 0500 0200SW R23L/1200N R23R/1000D FG NSC M41/M45 Q1024 R23/490147 NOSIG RMK QFE759";
let result = Metar::parse(metar);
evaluate_result(result.clone());
assert!(result.is_ok());
let result_metar = result.unwrap();
assert_eq!(MetarType::Metar, result_metar.report_type);
assert!(!result_metar.is_corrected);
assert_eq!("UEEE", result_metar.station);
assert!(!result_metar.is_auto);
assert!(!result_metar.is_nil);
assert_eq!(8u8, result_metar.time.date);
assert_eq!(16u8, result_metar.time.hour);
assert_eq!(30u8, result_metar.time.minute);
assert_eq!(Heading(310), result_metar.wind.dir.unwrap().clone());
assert_eq!(MetresPerSecond(1), result_metar.wind.speed.unwrap().clone());
assert!(result_metar.wind.varying.is_none());
assert!(result_metar.wind.gusting.is_none());
assert_eq!(Metres(500), result_metar.visibility.unwrap().clone());
assert!(!result_metar.rvr.is_empty());
assert_eq!("23L", result_metar.rvr.first().unwrap().runway);
assert_eq!(
Known(RvrDistance::Metres(1200u16)),
result_metar.rvr.first().unwrap().distance_low
);
assert_eq!(Unchanged, result_metar.rvr.first().unwrap().change);
assert_eq!(
RvrModifier::None,
result_metar.rvr.first().unwrap().modifier
);
assert_eq!("23R", result_metar.rvr.get(1).unwrap().runway);
assert_eq!(
Known(RvrDistance::Metres(1000u16)),
result_metar.rvr.get(1).unwrap().distance_low
);
assert_eq!(Decreased, result_metar.rvr.get(1).unwrap().change);
assert_eq!(RvrModifier::None, result_metar.rvr.get(1).unwrap().modifier);
assert_eq!(NoCloudDetected, result_metar.clouds.unwrap().clone());
assert!(result_metar.vert_visibility.is_none());
assert_eq!(1, result_metar.weather.len());
assert_eq!(Moderate, result_metar.weather.first().unwrap().intensity);
assert_eq!(1, result_metar.weather.first().unwrap().conditions.len());
assert_eq!(
Fog,
result_metar
.weather
.first()
.unwrap()
.conditions
.first()
.unwrap()
.clone()
);
assert_eq!(-41i32, *result_metar.temperature.unwrap());
assert_eq!(-45i32, *result_metar.dewpoint.unwrap());
assert_eq!(Hectopascals(1024), result_metar.pressure.unwrap().clone());
assert!(result_metar.recent.is_empty());
assert!(result_metar.remarks.is_some());
assert_eq!("RMK QFE759", result_metar.remarks.unwrap());
}
#[test]
fn test_metar_5() {
let metar = "CYWG 172000Z 30015G25KT 1 3/4SM R36/4000FT/D -SN BLSN BKN008 OVC040 M05/M08 Q1001 RMK SF5NS3 SLP134";
let result = Metar::parse(metar);
evaluate_result(result.clone());
assert!(result.is_ok());
let result_metar = result.unwrap();
assert_eq!(MetarType::Metar, result_metar.report_type);
assert!(!result_metar.is_corrected);
assert_eq!("CYWG", result_metar.station);
assert!(!result_metar.is_auto);
assert!(!result_metar.is_nil);
assert_eq!(17u8, result_metar.time.date);
assert_eq!(20u8, result_metar.time.hour);
assert_eq!(0u8, result_metar.time.minute);
assert_eq!(Heading(300), result_metar.wind.dir.unwrap().clone());
assert_eq!(Knot(15), result_metar.wind.speed.unwrap().clone());
assert!(result_metar.wind.varying.is_none());
assert_eq!(Knot(25), result_metar.wind.gusting.unwrap());
assert_eq!(
Visibility::StatuteMiles(1.75f32),
result_metar.visibility.unwrap().clone()
);
assert!(!result_metar.rvr.is_empty());
assert_eq!("36", result_metar.rvr.first().unwrap().runway);
assert_eq!(
Known(RvrDistance::Feet(4000u16)),
result_metar.rvr.first().unwrap().distance_low
);
assert_eq!(Decreased, result_metar.rvr.first().unwrap().change);
assert_eq!(
RvrModifier::None,
result_metar.rvr.first().unwrap().modifier
);
assert_eq!(CloudLayers, result_metar.clouds.unwrap().clone());
assert_eq!(
Broken(Normal, Some(8)),
result_metar.cloud_layers.first().unwrap().clone()
);
assert_eq!(
Overcast(Normal, Some(40)),
result_metar.cloud_layers.get(1).unwrap().clone()
);
assert!(result_metar.vert_visibility.is_none());
assert_eq!(2, result_metar.weather.len());
assert_eq!(Light, result_metar.weather.first().unwrap().intensity);
assert_eq!(1, result_metar.weather.first().unwrap().conditions.len());
assert_eq!(
Snow,
result_metar
.weather
.first()
.unwrap()
.conditions
.first()
.unwrap()
.clone()
);
assert_eq!(Moderate, result_metar.weather.get(1).unwrap().intensity);
assert_eq!(2, result_metar.weather.get(1).unwrap().conditions.len());
assert_eq!(
Snow,
result_metar
.weather
.first()
.unwrap()
.conditions
.first()
.unwrap()
.clone()
);
assert_eq!(
Blowing,
result_metar
.weather
.get(1)
.unwrap()
.conditions
.first()
.unwrap()
.clone()
);
assert_eq!(-5i32, *result_metar.temperature.unwrap());
assert_eq!(-8i32, *result_metar.dewpoint.unwrap());
assert_eq!(Hectopascals(1001), result_metar.pressure.unwrap().clone());
assert!(result_metar.recent.is_empty());
assert!(result_metar.remarks.is_some());
assert_eq!("RMK SF5NS3 SLP134", result_metar.remarks.unwrap());
}
#[test]
fn test_metar_6() {
let metar = "LTAE 250250Z VRB02KT 9999 BKN030 BKN080 06/05 Q1005 RESHRA NOSIG RMK RWY21 07004KT 040V100";
let result = Metar::parse(metar);
evaluate_result(result.clone());
assert!(result.is_ok());
let result_metar = result.unwrap();
assert_eq!(MetarType::Metar, result_metar.report_type);
assert!(!result_metar.is_corrected);
assert_eq!("LTAE", result_metar.station);
assert!(!result_metar.is_auto);
assert!(!result_metar.is_nil);
assert_eq!(25u8, result_metar.time.date);
assert_eq!(2u8, result_metar.time.hour);
assert_eq!(50u8, result_metar.time.minute);
assert_eq!(Variable, result_metar.wind.dir.unwrap().clone());
assert_eq!(Knot(2), result_metar.wind.speed.unwrap().clone());
assert!(result_metar.wind.varying.is_none());
assert!(result_metar.wind.gusting.is_none());
assert_eq!(Metres(9999), result_metar.visibility.unwrap().clone());
assert!(result_metar.rvr.is_empty());
assert_eq!(CloudLayers, result_metar.clouds.unwrap().clone());
assert_eq!(
Broken(Normal, Some(30)),
result_metar.cloud_layers.first().unwrap().clone()
);
assert_eq!(
Broken(Normal, Some(80)),
result_metar.cloud_layers.get(1).unwrap().clone()
);
assert!(result_metar.vert_visibility.is_none());
assert!(result_metar.weather.is_empty());
assert_eq!(6i32, *result_metar.temperature.unwrap());
assert_eq!(5i32, *result_metar.dewpoint.unwrap());
assert_eq!(Hectopascals(1005), result_metar.pressure.unwrap().clone());
assert_eq!(Known(Showers), result_metar.recent.first().unwrap().clone());
assert_eq!(Known(Rain), result_metar.recent.get(1).unwrap().clone());
assert!(result_metar.remarks.is_some());
assert_eq!("RMK RWY21 07004KT 040V100", result_metar.remarks.unwrap());
}
#[test]
fn test_metar_online_eddf() {
let url = format!("{}EDDF", URL);
let client = Client::new();
let response = client.get(url).send();
let metar: String;
match response {
Ok(data) => metar = data.text().unwrap(),
Err(_) => panic!(),
}
println!("Downloaded METAR: {}", metar);
let result = Metar::parse(metar);
evaluate_result(result);
}
#[test]
fn test_metar_online_egll() {
let url = format!("{}EGLL", URL);
let client = Client::new();
let response = client.get(url).send();
let metar: String;
match response {
Ok(data) => metar = data.text().unwrap(),
Err(_) => panic!(),
}
println!("Downloaded METAR: {}", metar);
let result = Metar::parse(metar);
evaluate_result(result);
}
#[test]
fn test_metar_online_yssy() {
let url = format!("{}YSSY", URL);
let client = Client::new();
let response = client.get(url).send();
let metar: String;
match response {
Ok(data) => metar = data.text().unwrap(),
Err(_) => panic!(),
}
println!("Downloaded METAR: {}", metar);
let result = Metar::parse(metar);
evaluate_result(result);
}
#[test]
fn test_metar_online_kjfk() {
let url = format!("{}KJFK", URL);
let client = Client::new();
let response = client.get(url).send();
let metar: String;
match response {
Ok(data) => metar = data.text().unwrap(),
Err(_) => panic!(),
}
println!("Downloaded METAR: {}", metar);
let result = Metar::parse(metar);
evaluate_result(result);
}
#[test]
fn test_metar_online_ksfo() {
let url = format!("{}KSFO", URL);
let client = Client::new();
let response = client.get(url).send();
let metar: String;
match response {
Ok(data) => metar = data.text().unwrap(),
Err(_) => panic!(),
}
println!("Downloaded METAR: {}", metar);
let result = Metar::parse(metar);
evaluate_result(result);
}
#[test]
fn test_metar_online_klax() {
let url = format!("{}KLAX", URL);
let client = Client::new();
let response = client.get(url).send();
let metar: String;
match response {
Ok(data) => metar = data.text().unwrap(),
Err(_) => panic!(),
}
println!("Downloaded METAR: {}", metar);
let result = Metar::parse(metar);
evaluate_result(result);
}
#[test]
fn test_metar_online_bikf() {
let url = format!("{}BIKF", URL);
let client = Client::new();
let response = client.get(url).send();
let metar: String;
match response {
Ok(data) => metar = data.text().unwrap(),
Err(_) => panic!(),
}
println!("Downloaded METAR: {}", metar);
let result = Metar::parse(metar);
evaluate_result(result);
}
#[test]
fn test_metar_manual() {
let metar =
"KCMI 301116Z 00000KT 1/4SM R32R/1200V3500FT/N FG CLR 19/19 A2990 RMK AO2 T01940189";
let result = Metar::parse(metar);
evaluate_result(result);
}
fn evaluate_result(result: Result<Metar, MetarError>) {
if result.is_ok() {
assert!(result.is_ok());
println!("--------------------------------------------");
println!("--------------------------------------------");
println!("OK! Result is:");
println!("{:#?}", result.clone().unwrap());
println!("--------------------------------------------");
println!("--------------------------------------------");
} else {
let error = result.err().unwrap();
println!("--------------------------------------------");
println!("--------------------------------------------");
println!("ERROR! Error is:");
println!("Input: {}", error.string);
println!("Start: {}", error.start);
println!("Length: {}", error.length);
println!("Error message: {}", error.variant);
println!("Error part: {}", error.string.get(error.start..).unwrap());
println!("--------------------------------------------");
println!("--------------------------------------------");
}
}
}