add point finder from args

This commit is contained in:
Dr. Matthias Ratajczak
2023-01-05 13:31:51 +01:00
parent 508684fd72
commit 65881f7174
5 changed files with 107 additions and 10 deletions
+49 -1
View File
@@ -1,6 +1,6 @@
use std::fmt::{Debug, Display};
use anyhow::Result;
use anyhow::{Context, Result};
use chrono::{DateTime, Local, TimeZone, Utc};
use serde::{de, Deserialize, Deserializer};
@@ -72,3 +72,51 @@ pub fn format_departures(response: Response) -> String {
let departures: Vec<String> = response.departures.iter().map(|d| d.to_string()).collect();
departures.join("\n\n")
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct PointFinderResponse {
#[serde(deserialize_with = "deserialize_points", rename = "Points")]
pub point: Point,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct Point {
pub stopid: String,
pub name: String,
pub area: Option<String>,
}
impl From<(&str, &str, Option<&str>)> for Point {
fn from(value: (&str, &str, Option<&str>)) -> Self {
Self {
stopid: value.0.into(),
name: value.1.into(),
area: value.2.map(|s| s.into()),
}
}
}
/// Deserialize a Point Response in the form of
/// '\"33000742|||Helmholtzstraße|5655904|4621157|0||\"'
fn extract_data_from_response(line: &str) -> Result<Point> {
let mut iter = line.trim_start_matches("\\\"").split_terminator('|');
let stopid = iter.next().context("getting stopid from line")?;
let area = iter.nth(1).context("getting area from line").ok();
let name = iter.next().context("getting stop name from line")?;
Ok((stopid, name, area).into())
}
fn deserialize_points<'de, D>(deserializer: D) -> Result<Point, D::Error>
where
D: Deserializer<'de>,
{
let stops: Vec<String> = Vec::deserialize(deserializer)?;
let first_stop_line = stops
.first()
.ok_or_else(|| de::Error::custom("could not get first stop"))?;
let point = extract_data_from_response(first_stop_line).map_err(de::Error::custom)?;
Ok(point)
}