1use obex_core::client::ObexError;
4use obex_core::TransportError;
5use quick_xml::{events::Event, Reader, XmlVersion};
6use thiserror::Error;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum EventType {
11 NewMessage,
13 DeliverySuccess,
15 SendingSuccess,
17 DeliveryFailure,
19 SendingFailure,
21 MessageDeleted,
23 MessageShift,
25 MemoryFull,
27 MemoryAvailable,
29 ReadStatusChanged,
31}
32
33#[derive(Debug, Clone, PartialEq, Eq)]
35pub struct MnsEvent {
36 event_type: EventType,
37 handle: Option<String>,
38 folder: Option<String>,
39 old_folder: Option<String>,
40 msg_type: Option<String>,
41 datetime: Option<String>,
42}
43
44impl MnsEvent {
45 #[must_use]
47 pub const fn event_type(&self) -> EventType {
48 self.event_type
49 }
50
51 #[must_use]
53 pub fn handle(&self) -> Option<&str> {
54 self.handle.as_deref()
55 }
56
57 #[must_use]
59 pub fn folder(&self) -> Option<&str> {
60 self.folder.as_deref()
61 }
62
63 #[must_use]
65 pub fn old_folder(&self) -> Option<&str> {
66 self.old_folder.as_deref()
67 }
68
69 #[must_use]
71 pub fn msg_type(&self) -> Option<&str> {
72 self.msg_type.as_deref()
73 }
74
75 #[must_use]
77 pub fn datetime(&self) -> Option<&str> {
78 self.datetime.as_deref()
79 }
80}
81
82#[derive(Debug, Error)]
84pub enum MnsError {
85 #[error("XML error: {0}")]
87 Parse(#[from] quick_xml::Error),
88 #[error("attribute error: {0}")]
90 Attr(#[from] quick_xml::events::attributes::AttrError),
91 #[error("unknown event type: {0}")]
93 UnknownEventType(String),
94 #[error("<event> element has no type attribute")]
96 MissingEventType,
97 #[error("MAP-event-report contained no <event> element")]
99 MissingEvent,
100 #[error("OBEX: {0}")]
102 Obex(#[from] ObexError),
103 #[error("transport: {0}")]
105 Transport(#[from] TransportError),
106 #[error("unexpected end of stream")]
108 UnexpectedEof,
109 #[error("unexpected OBEX opcode {0:#04x} from MNS client")]
111 UnexpectedOpcode(u8),
112 #[error("CONNECT Target UUID does not match MNS service UUID")]
114 InvalidTarget,
115}
116
117pub fn parse_event_report(xml: &[u8]) -> Result<MnsEvent, MnsError> {
129 let mut reader = Reader::from_reader(xml);
130 reader.config_mut().trim_text(true);
131 let mut buf = Vec::with_capacity(256);
132 loop {
133 match reader.read_event_into(&mut buf)? {
134 Event::Empty(e) | Event::Start(e) if e.name().as_ref() == b"event" => {
135 let mut raw_type: Option<String> = None;
136 let mut handle = None;
137 let mut folder = None;
138 let mut old_folder = None;
139 let mut msg_type = None;
140 let mut datetime = None;
141 for attr in e.attributes() {
142 let a = attr?;
143 let val = a.normalized_value(XmlVersion::Implicit1_0)?.into_owned();
144 match a.key.as_ref() {
145 b"type" => raw_type = Some(val),
146 b"handle" => handle = Some(val),
147 b"folder" => folder = Some(val),
148 b"old_folder" => old_folder = Some(val),
149 b"msg_type" => msg_type = Some(val),
150 b"datetime" => datetime = Some(val),
151 _ => {}
152 }
153 }
154 let event_type = match raw_type {
155 Some(ref s) => event_type_from_str(s)?,
156 None => return Err(MnsError::MissingEventType),
157 };
158 return Ok(MnsEvent { event_type, handle, folder, old_folder, msg_type, datetime });
159 }
160 Event::Eof => return Err(MnsError::MissingEvent),
161 _ => {}
162 }
163 buf.clear();
164 }
165}
166
167fn event_type_from_str(s: &str) -> Result<EventType, MnsError> {
168 match s {
169 "NewMessage" => Ok(EventType::NewMessage),
170 "DeliverySuccess" => Ok(EventType::DeliverySuccess),
171 "SendingSuccess" => Ok(EventType::SendingSuccess),
172 "DeliveryFailure" => Ok(EventType::DeliveryFailure),
173 "SendingFailure" => Ok(EventType::SendingFailure),
174 "MessageDeleted" => Ok(EventType::MessageDeleted),
175 "MessageShift" => Ok(EventType::MessageShift),
176 "MemoryFull" => Ok(EventType::MemoryFull),
177 "MemoryAvailable" => Ok(EventType::MemoryAvailable),
178 "ReadStatusChanged" => Ok(EventType::ReadStatusChanged),
179 other => Err(MnsError::UnknownEventType(other.to_owned())),
180 }
181}