1 #![allow(unused)]
2 
3 extern crate quick_xml;
4 
5 use quick_xml::events::Event;
6 use quick_xml::Reader;
7 use std::io::Read;
8 
9 struct Resource {
10     etag: String,
11     calendar_data: String,
12 }
13 
14 struct Prop {
15     namespace: String,
16     local_name: String,
17     value: String,
18 }
19 
20 impl Prop {
new() -> Prop21     fn new() -> Prop {
22         Prop {
23             namespace: String::new(),
24             local_name: String::new(),
25             value: String::new(),
26         }
27     }
28 }
29 
30 struct PropStat {
31     status: String,
32     props: Vec<Prop>,
33 }
34 
35 impl PropStat {
new() -> PropStat36     fn new() -> PropStat {
37         PropStat {
38             status: String::new(),
39             props: Vec::<Prop>::new(),
40         }
41     }
42 }
43 
44 struct Response {
45     href: String,
46     propstats: Vec<PropStat>,
47 }
48 
49 impl Response {
new() -> Response50     fn new() -> Response {
51         Response {
52             href: String::new(),
53             propstats: Vec::<PropStat>::new(),
54         }
55     }
56 }
57 
parse_report(xml_data: &str) -> Vec<Resource>58 fn parse_report(xml_data: &str) -> Vec<Resource> {
59     let result = Vec::<Resource>::new();
60 
61     let mut reader = Reader::from_str(xml_data);
62     reader.trim_text(true);
63 
64     let mut count = 0;
65     let mut buf = Vec::new();
66     let mut ns_buffer = Vec::new();
67 
68     #[derive(Clone, Copy)]
69     enum State {
70         Root,
71         MultiStatus,
72         Response,
73         Success,
74         Error,
75     };
76 
77     let mut responses = Vec::<Response>::new();
78     let mut current_response = Response::new();
79     let mut current_prop = Prop::new();
80 
81     let mut depth = 0;
82     let mut state = State::MultiStatus;
83 
84     loop {
85         match reader.read_namespaced_event(&mut buf, &mut ns_buffer) {
86             Ok((namespace_value, Event::Start(e))) => {
87                 let namespace_value = namespace_value.unwrap_or_default();
88                 match (depth, state, namespace_value, e.local_name()) {
89                     (0, State::Root, b"DAV:", b"multistatus") => state = State::MultiStatus,
90                     (1, State::MultiStatus, b"DAV:", b"response") => {
91                         state = State::Response;
92                         current_response = Response::new();
93                     }
94                     (2, State::Response, b"DAV:", b"href") => {
95                         current_response.href = e.unescape_and_decode(&reader).unwrap();
96                     }
97                     _ => {}
98                 }
99                 depth += 1;
100             }
101             Ok((namespace_value, Event::End(e))) => {
102                 let namespace_value = namespace_value.unwrap_or_default();
103                 let local_name = e.local_name();
104                 match (depth, state, &*namespace_value, local_name) {
105                     (1, State::MultiStatus, b"DAV:", b"multistatus") => state = State::Root,
106                     (2, State::MultiStatus, b"DAV:", b"multistatus") => state = State::MultiStatus,
107                     _ => {}
108                 }
109                 depth -= 1;
110             }
111             Ok((_, Event::Eof)) => break,
112             Err(e) => break,
113             _ => (),
114         }
115     }
116     result
117 }
118 
main()119 fn main() {
120     let test_data = r#"
121 <?xml version="1.0" encoding="UTF-8"?>
122 <D:multistatus xmlns:D="DAV:" xmlns:caldav="urn:ietf:params:xml:ns:caldav"
123     xmlns:cs="http://calendarserver.org/ns/" xmlns:ical="http://apple.com/ns/ical/">
124  <D:response xmlns:carddav="urn:ietf:params:xml:ns:carddav"
125     xmlns:cm="http://cal.me.com/_namespace/" xmlns:md="urn:mobileme:davservices">
126   <D:href>
127   /caldav/v2/johndoh%40gmail.com/events/07b7it7uonpnlnvjldr0l1ckg8%40google.com.ics
128   </D:href>
129   <D:propstat>
130    <D:status>HTTP/1.1 200 OK</D:status>
131    <D:prop>
132     <D:getetag>"63576798396"</D:getetag>
133     <caldav:calendar-data>BEGIN:VCALENDAR</caldav:calendar-data>
134    </D:prop>
135   </D:propstat>
136  </D:response>
137 </D:multistatus>
138 "#;
139 
140     parse_report(test_data);
141 }
142