This is a UPnP client library for Rust.

Merge pull request #10 from tsirysndr/xmlerrors-to-anyhow

Xmlerrors to anyhow

authored by tsiry-sandratraina.com and committed by GitHub bbcfce2e d16ad47a

+1 -1
Cargo.toml
··· 1 1 [package] 2 2 name = "upnp-client" 3 - version = "0.1.8" 3 + version = "0.1.9" 4 4 edition = "2021" 5 5 repository = "https://github.com/tsirysndr/upnp-client-rs" 6 6 license = "MIT"
+4 -4
README.md
··· 42 42 43 43 #[tokio::main] 44 44 async fn main() -> Result<(), Box<dyn std::error::Error>> { 45 - let devices = discover_pnp_locations(); 45 + let devices = discover_pnp_locations().await?; 46 46 tokio::pin!(devices); 47 47 48 48 while let Some(device) = devices.next().await { ··· 107 107 108 108 #[tokio::main] 109 109 async fn main() -> Result<(), Box<dyn std::error::Error>> { 110 - let devices = discover_pnp_locations(); 110 + let devices = discover_pnp_locations().await?; 111 111 tokio::pin!(devices); 112 112 113 113 let mut kodi_device: Option<Device> = None; ··· 120 120 } 121 121 122 122 let kodi_device = kodi_device.unwrap(); 123 - let device_client = DeviceClient::new(&kodi_device.location).connect().await?; 123 + let device_client = DeviceClient::new(&kodi_device.location)?.connect().await?; 124 124 let media_renderer = MediaRendererClient::new(device_client); 125 125 126 126 let options = LoadOptions { ··· 164 164 - [UPnP AV ContentDirectory v3 Service](http://upnp.org/specs/av/UPnP-av-ContentDirectory-v3-Service.pdf) 165 165 166 166 ### License 167 - MIT 167 + MIT
+13 -19
src/device_client.rs
··· 1 - use std::{ 2 - collections::HashMap, 3 - env, 4 - net::TcpListener, 5 - sync::{ 6 - Arc, 7 - }, 8 - time::Duration, 9 - }; 1 + use std::{collections::HashMap, env, net::TcpListener, sync::Arc, time::Duration}; 10 2 11 3 use crate::{ 12 4 parser::{ ··· 110 102 111 103 for (name, value) in params { 112 104 let mut param = XMLElement::new(name.as_str()); 113 - param.add_text(value)?; 114 - action.add_child(param)?; 105 + param.add_text(value).map_err(|e| anyhow!("{:?}", e))?; 106 + action.add_child(param).map_err(|e| anyhow!("{:?}", e))?; 115 107 } 116 108 117 - body.add_child(action)?; 118 - envelope.add_child(body)?; 109 + body.add_child(action).map_err(|e| anyhow!("{:?}", e))?; 110 + envelope.add_child(body).map_err(|e| anyhow!("{:?}", e))?; 119 111 120 112 xml.set_root_element(envelope); 121 113 122 114 let mut writer: Vec<u8> = Vec::new(); 123 - xml.generate(&mut writer)?; 115 + xml.generate(&mut writer).map_err(|e| anyhow!("{:?}", e))?; 124 116 let xml = String::from_utf8(writer)?; 125 117 126 118 let soap_action = format!("\"{}#{}\"", service.service_type, action_name); ··· 136 128 .send() 137 129 .await 138 130 .map_err(|e| anyhow!(e.to_string()))?; 139 - res 140 - .body_string() 141 - .await 142 - .map_err(|e| anyhow!(e.to_string())) 131 + res.body_string().await.map_err(|e| anyhow!(e.to_string())) 143 132 } 144 133 145 134 async fn get_service_description(&self, service_id: &str) -> Result<Service> { ··· 148 137 .services 149 138 .iter() 150 139 .find(|s| s.service_id == service_id) 151 - .ok_or_else(|| anyhow!("Service with requested service_id {} does not exist", service_id))?; 140 + .ok_or_else(|| { 141 + anyhow!( 142 + "Service with requested service_id {} does not exist", 143 + service_id 144 + ) 145 + })?; 152 146 return Ok(service.clone()); 153 147 } 154 148 Err(anyhow!("Device not connected"))
+20 -8
src/parser.rs
··· 93 93 Some(element) => { 94 94 return Ok(element.text().to_string()); 95 95 } 96 - None => { 97 - Ok("".to_string()) 98 - } 96 + None => Ok("".to_string()), 99 97 } 100 98 } 101 99 None => Ok("".to_string()), ··· 373 371 let parser = EventReader::from_str(xml_root); 374 372 let mut current_play_mode: Option<String> = None; 375 373 for e in parser.into_iter().flatten() { 376 - if let XmlEvent::StartElement { name, attributes, .. } = e { 374 + if let XmlEvent::StartElement { 375 + name, attributes, .. 376 + } = e 377 + { 377 378 if name.local_name == "CurrentPlayMode" { 378 379 for attr in attributes { 379 380 if attr.name.local_name == "val" { ··· 390 391 let parser = EventReader::from_str(xml_root); 391 392 let mut transport_state: Option<String> = None; 392 393 for e in parser.into_iter().flatten() { 393 - if let XmlEvent::StartElement { name, attributes, .. } = e { 394 + if let XmlEvent::StartElement { 395 + name, attributes, .. 396 + } = e 397 + { 394 398 if name.local_name == "TransportState" { 395 399 for attr in attributes { 396 400 if attr.name.local_name == "val" { ··· 407 411 let parser = EventReader::from_str(xml_root); 408 412 let mut av_transport_uri_metadata: Option<String> = None; 409 413 for e in parser.into_iter().flatten() { 410 - if let XmlEvent::StartElement { name, attributes, .. } = e { 414 + if let XmlEvent::StartElement { 415 + name, attributes, .. 416 + } = e 417 + { 411 418 if name.local_name == "AVTransportURIMetaData" { 412 419 for attr in attributes { 413 420 if attr.name.local_name == "val" { ··· 424 431 let parser = EventReader::from_str(xml_root); 425 432 let mut current_track_metadata: Option<String> = None; 426 433 for e in parser.into_iter().flatten() { 427 - if let XmlEvent::StartElement { name, attributes, .. } = e { 434 + if let XmlEvent::StartElement { 435 + name, attributes, .. 436 + } = e 437 + { 428 438 if name.local_name == "CurrentTrackMetaData" { 429 439 for attr in attributes { 430 440 if attr.name.local_name == "val" { ··· 778 788 </device> 779 789 </root>"#; 780 790 781 - let result = parse_services("http://xxxxxx:1337/", XML_ROOT).await; 791 + let result = parse_services("http://xxxxxx:1337/", XML_ROOT) 792 + .await 793 + .unwrap(); 782 794 assert_eq!(result.len(), 0); 783 795 } 784 796 }