learn-rust icon indicating copy to clipboard operation
learn-rust copied to clipboard

Step3 unclear, possible successful compilation without clearly stated completions criteria

Open Immortalin opened this issue 7 years ago • 1 comments

extern crate reqwest;
extern crate xml;

use self::xml::reader::{EventReader, XmlEvent};
use reqwest::Client;
use reqwest::Response;

fn main() {
    let client = Client::new();

    let xml: String = get_mta_status(&client);

    // passing `String` wont work because String doesnt implement std::io::Read
    // parse_xml(xml);
    let readable: &[u8] = xml.as_bytes();
    let lines = parse_xml(readable);
    for line in lines.iter() {
        println!("{:?}", line);
    };
}

fn get_mta_status(client: &Client) -> String {
    let mut resp: Response = client
        .get("http://web.mta.info/status/serviceStatus.txt")
        .send()
        .unwrap();
    let body: String = resp.text().unwrap();

    body
}

#[derive(Debug)]
struct Line {
    name: String,
    status: String,
}

impl Line {
    fn empty() -> Line {
        Line {
            name: "".into(),
            status: "".into(),
        }
    }

    // fn adt
}

/// Because we are using a XML event streaming
/// library we need to maintain state of which
/// tag we are processing.
enum XmlTag {
    TimeStamp,
    LineName,
    LineStatus,
    Ignore,
}

fn parse_xml<T>(readable: T) -> Vec<Line>
where
    T: std::io::Read,
{
    let reader = EventReader::new(readable);
    // This will hold the current tag we are processing.
    // We set it to a default value or `Ignore`.
    let mut xml_tag: XmlTag = XmlTag::Ignore;

    //TODO Populate the `Vec` by `push`ing `temp_line` elements
    // into it.
    let lines = Vec::new();

    let temp_line = Line::empty();

    for e in reader {

        match e {
            Ok(XmlEvent::StartElement { name, .. }) => {
                let ref_name: &str = name.local_name.as_ref();
                match ref_name {
                    "line" => {
                        //FIXME
                        // temp_line = Line::empty();
                        // temp_line 
                    }

                    "timestamp" => {
                        xml_tag = XmlTag::TimeStamp;
                        print!("{}: ", name);
                    }

                    "name" => {
                        xml_tag = XmlTag::LineName;
                    }

                    "status" => {
                        xml_tag = XmlTag::LineStatus;
                    }

                    _ => {
                        xml_tag = XmlTag::Ignore;
                    }
                }
            }

            Ok(XmlEvent::Characters(txt)) => match xml_tag {
                XmlTag::TimeStamp => println!("{}", txt),

                XmlTag::LineName => {
                }

                XmlTag::LineStatus => {
                }

                _ => (),
            },

            Ok(XmlEvent::EndElement { name }) => {
                let ref_name: &str = name.local_name.as_ref();
                match ref_name {
                    "line" => {
                        //FIXME
                    }

                    // we only care about subway
                    "subway" => break,

                    _ => (),
                }
            }

            Err(e) => {
                println!("Error: {}", e);
                break;
            }

            _ => (),
        }
    }

    lines
}

Immortalin avatar Sep 19 '18 04:09 Immortalin

@Immortalin hi I can see how this can be confusing and daunting. Want to take a stab at adding better comments?

I think the the double match ref_name { "line" => ... match is the confusing part.

This was my attempt at hinting that the second match can be used to push a new struct Line and build the Vec of lines.

toidiu avatar Sep 25 '18 15:09 toidiu