├── .gitignore ├── .idea ├── .gitignore ├── inspectionProfiles │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── vcs.xml └── xml_serde.iml ├── Cargo.toml ├── README.md └── src ├── de.rs ├── error.rs ├── lib.rs ├── ser.rs └── tag.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/xml_serde.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "xml_serde" 3 | version = "1.2.3" 4 | edition = "2021" 5 | authors = ["Q "] 6 | license = "MIT" 7 | repository = "https://github.com/as207960/xml-serde" 8 | description = "Namespace aware XML (de)serializer utilizing Serde" 9 | readme = "README.md" 10 | 11 | [dependencies] 12 | serde = "1" 13 | xml-rs = "0.8" 14 | hex = "0.4" 15 | regex = "1" 16 | log = "0.4" 17 | itertools = "0.9" 18 | once_cell = "1.9" 19 | 20 | [dev-dependencies] 21 | pretty_env_logger = "0.4" 22 | serde_derive = "1" 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Namespace aware XML (de)serializer for Rust utilizing Serde 2 | 3 | ```rust 4 | // XML elements can be specified with structs 5 | #[derive(Debug, Serialize, Deserialize)] 6 | pub struct BulkObservable { 7 | // Required attributes can easily be defined, with the format of {namespace}ns-prefix:element 8 | #[serde(rename = "{urn:ietf:params:xml:ns:iodef-2.0}iodef:BulkObservableList")] 9 | pub list: String, 10 | 11 | // Repeated and optional elements can be defined with Vec and Option 12 | #[serde(rename = "{urn:ietf:params:xml:ns:iodef-2.0}iodef:AdditionalData", default, skip_serializing_if="Vec::is_empty")] 13 | pub additional_data: Vec, 14 | #[serde(rename = "{urn:ietf:params:xml:ns:iodef-2.0}iodef:BulkObservableFormat", default, skip_serializing_if="Option::is_none")] 15 | pub format: Option, 16 | 17 | // Element attributes can be specified with the $attr: prefix 18 | #[serde(rename = "$attr:type")] 19 | pub bulk_type: BulkObservableType, 20 | #[serde(rename = "$attr:ext-type", default, skip_serializing_if="Option::is_none")] 21 | pub bulk_ext_type: Option, 22 | 23 | // Textual element content can be set with the special name $value 24 | #[serde(rename = "$value")] 25 | pub value: f64, 26 | } 27 | 28 | // Enumerated values can also be defined 29 | #[derive(Debug, Serialize, Deserialize)] 30 | pub enum ConfidenceRating { 31 | #[serde(rename = "low")] 32 | Low, 33 | #[serde(rename = "medium")] 34 | Medium, 35 | #[serde(rename = "high")] 36 | High, 37 | #[serde(rename = "numeric")] 38 | Numeric, 39 | #[serde(rename = "unknown")] 40 | Unknown 41 | } 42 | 43 | // As can enumerated objects 44 | #[derive(Debug, Serialize, Deserialize)] 45 | pub enum IndicatorExpressionInner { 46 | #[serde(rename = "{urn:ietf:params:xml:ns:iodef-2.0}IndicatorExpression")] 47 | IndicatorExpression(IndicatorExpression), 48 | #[serde(rename = "{urn:ietf:params:xml:ns:iodef-2.0}Observable")] 49 | Observable(Observable), 50 | #[serde(rename = "{urn:ietf:params:xml:ns:iodef-2.0}ObservableReference")] 51 | ObservableReference(ObservableReference), 52 | #[serde(rename = "{urn:ietf:params:xml:ns:iodef-2.0}IndicatorReference")] 53 | IndicatorReference(IndicatorReference), 54 | #[serde(rename = "{urn:ietf:params:xml:ns:iodef-2.0}AdditionalData")] 55 | AdditionalData(ExtensionType), 56 | } 57 | ``` 58 | -------------------------------------------------------------------------------- /src/de.rs: -------------------------------------------------------------------------------- 1 | use std::borrow::Cow; 2 | use std::ops::{AddAssign, MulAssign}; 3 | 4 | use serde::{de, Deserialize}; 5 | use serde::de::IntoDeserializer; 6 | use crate::Tag; 7 | 8 | // TODO: revert Iterator to this if trait_alias stabilizes 9 | // pub trait XMLIter = Iterator>; 10 | type XmlRes = xml::reader::Result; 11 | 12 | pub struct Deserializer> { 13 | reader: itertools::MultiPeek, 14 | depth: u64, 15 | is_map_value: bool, 16 | is_greedy: bool, 17 | is_value: bool, 18 | reset_peek_offset: u64, 19 | } 20 | 21 | fn new_reader>(iter: I) -> itertools::MultiPeek> { 22 | itertools::multipeek(Box::new(iter.into_iter().filter(|e| match e { 23 | &Ok(xml::reader::XmlEvent::ProcessingInstruction { ..}) => { 24 | trace!("discarding processing instruction: {:?}", e.as_ref().unwrap()); 25 | false 26 | }, 27 | _ => true, 28 | }))) 29 | } 30 | 31 | pub fn from_str<'a, T: Deserialize<'a>>(s: &'a str) -> crate::Result { 32 | let conf = xml::ParserConfig::new() 33 | .trim_whitespace(true) 34 | .whitespace_to_characters(true) 35 | .replace_unknown_entity_references(true); 36 | let mut event_reader = xml::reader::EventReader::new_with_config(s.as_bytes(), conf); 37 | match event_reader.next()? { 38 | xml::reader::XmlEvent::StartDocument { 39 | version, 40 | encoding, 41 | standalone 42 | } => { 43 | trace!("start_document({:?}, {:?}, {:?})", version, encoding, standalone); 44 | } 45 | _ => return Err(crate::Error::ExpectedElement) 46 | } 47 | let mut deserializer = Deserializer { 48 | reader: new_reader(event_reader), 49 | depth: 0, 50 | is_map_value: false, 51 | is_greedy: true, 52 | is_value: false, 53 | reset_peek_offset: 0, 54 | }; 55 | let t = T::deserialize(&mut deserializer)?; 56 | Ok(t) 57 | } 58 | 59 | pub fn from_string<'a, T: Deserialize<'a>>(s: String) -> crate::Result { 60 | let conf = xml::ParserConfig::new() 61 | .trim_whitespace(true) 62 | .whitespace_to_characters(true) 63 | .replace_unknown_entity_references(true); 64 | let mut event_reader = xml::reader::EventReader::new_with_config(s.as_bytes(), conf); 65 | match event_reader.next()? { 66 | xml::reader::XmlEvent::StartDocument { 67 | version, 68 | encoding, 69 | standalone 70 | } => { 71 | trace!("start_document({:?}, {:?}, {:?})", version, encoding, standalone); 72 | } 73 | _ => return Err(crate::Error::ExpectedElement) 74 | } 75 | let mut deserializer = Deserializer { 76 | reader: new_reader(event_reader), 77 | depth: 0, 78 | is_map_value: false, 79 | is_greedy: true, 80 | is_value: false, 81 | reset_peek_offset: 0, 82 | }; 83 | let t = T::deserialize(&mut deserializer)?; 84 | Ok(t) 85 | } 86 | 87 | pub fn from_events<'a, T: Deserialize<'a>>(s: &[xml::reader::Result]) -> crate::Result { 88 | let mut reader = new_reader(s.into_iter().map(|r| r.to_owned())); 89 | if let Ok(xml::reader::XmlEvent::StartDocument { .. }) = reader.peek().ok_or(crate::Error::ExpectedElement)? { 90 | match reader.next() { 91 | Some(Ok(xml::reader::XmlEvent::StartDocument { 92 | version, 93 | encoding, 94 | standalone 95 | })) => { 96 | trace!("start_document({:?}, {:?}, {:?})", version, encoding, standalone); 97 | } 98 | _ => unreachable!() 99 | } 100 | } 101 | reader.reset_peek(); 102 | let mut deserializer = Deserializer { 103 | reader, 104 | depth: 0, 105 | is_map_value: false, 106 | is_greedy: true, 107 | is_value: false, 108 | reset_peek_offset: 0, 109 | }; 110 | let t = T::deserialize(&mut deserializer)?; 111 | Ok(t) 112 | } 113 | 114 | impl> Deserializer { 115 | fn set_map_value(&mut self) { 116 | trace!("set_map_value()"); 117 | self.is_map_value = true; 118 | } 119 | 120 | pub fn unset_map_value(&mut self) -> bool { 121 | self.is_value = false; 122 | std::mem::replace(&mut self.is_map_value, false) 123 | } 124 | 125 | fn set_is_value(&mut self) { 126 | trace!("set_is_value()"); 127 | self.is_value = true; 128 | } 129 | 130 | pub fn unset_is_value(&mut self) -> bool { 131 | std::mem::replace(&mut self.is_value, false) 132 | } 133 | 134 | fn set_not_greedy(&mut self) { 135 | trace!("set_not_greedy()"); 136 | self.is_greedy = false; 137 | } 138 | 139 | pub fn unset_not_greedy(&mut self) -> bool { 140 | trace!("unset_not_greedy()"); 141 | self.reset_peek_offset = 0; 142 | std::mem::replace(&mut self.is_greedy, true) 143 | } 144 | 145 | fn peek(&mut self) -> crate::Result<&xml::reader::XmlEvent> { 146 | let next = match match self.reader.peek() { 147 | Some(n) => n, 148 | None => return Ok(&xml::reader::XmlEvent::EndDocument) 149 | } { 150 | Ok(n) => n, 151 | Err(e) => return Err(e.into()) 152 | }; 153 | trace!("peek() -> {:?}", next); 154 | Ok(next) 155 | } 156 | 157 | fn reset_peek(&mut self) { 158 | self.reader.reset_peek(); 159 | for _ in 0..self.reset_peek_offset { 160 | self.reader.peek(); 161 | } 162 | } 163 | 164 | fn next(&mut self) -> crate::Result { 165 | let next = match self.reader.next() { 166 | Some(n) => n, 167 | None => return Err(crate::Error::ExpectedElement) 168 | }?; 169 | match next { 170 | xml::reader::XmlEvent::StartElement { .. } => { 171 | self.depth += 1; 172 | } 173 | xml::reader::XmlEvent::EndElement { .. } => { 174 | self.depth -= 1; 175 | } 176 | _ => {} 177 | } 178 | trace!("next() -> {:?}; depth = {}", next, self.depth); 179 | Ok(next) 180 | } 181 | 182 | fn read_inner_value crate::Result>(&mut self, f: F) -> crate::Result { 183 | trace!("read_inner_value()"); 184 | let old_greedy = self.is_greedy; 185 | let ret = if self.unset_map_value() { 186 | match self.next()? { 187 | xml::reader::XmlEvent::StartElement { name, .. } => { 188 | let result = f(self)?; 189 | self.expect_end_element(name)?; 190 | Ok(result) 191 | } 192 | _ => Err(crate::Error::ExpectedElement) 193 | } 194 | } else { 195 | f(self) 196 | }; 197 | self.is_greedy = old_greedy; 198 | ret 199 | } 200 | 201 | fn read_inner_value_attrs) -> crate::Result>(&mut self, f: F) -> crate::Result { 202 | trace!("read_inner_value()"); 203 | let old_greedy = self.is_greedy; 204 | let ret = if self.unset_map_value() { 205 | match self.next()? { 206 | xml::reader::XmlEvent::StartElement { name, attributes, .. } => { 207 | let result = f(self, attributes)?; 208 | self.expect_end_element(name)?; 209 | Ok(result) 210 | } 211 | _ => Err(crate::Error::ExpectedElement) 212 | } 213 | } else { 214 | f(self, vec![]) 215 | }; 216 | self.is_greedy = old_greedy; 217 | ret 218 | } 219 | 220 | fn expect_end_element(&mut self, old_name: xml::name::OwnedName) -> crate::Result<()> { 221 | trace!("expect_end_element({:?})", old_name); 222 | match self.next()? { 223 | xml::reader::XmlEvent::EndElement { name } => { 224 | if name == old_name { 225 | Ok(()) 226 | } else { 227 | Err(crate::Error::ExpectedElement) 228 | } 229 | } 230 | _ => Err(crate::Error::ExpectedElement) 231 | } 232 | } 233 | 234 | fn parse_string(&mut self) -> crate::Result { 235 | trace!("prase_string()"); 236 | self.read_inner_value(|this| { 237 | match this.peek()? { 238 | xml::reader::XmlEvent::EndElement { 239 | .. 240 | } => return Ok(String::new()), 241 | _ => {} 242 | } 243 | match this.next()? { 244 | xml::reader::XmlEvent::CData(s) | xml::reader::XmlEvent::Characters(s) => { 245 | Ok(s) 246 | } 247 | xml::reader::XmlEvent::StartElement { 248 | name, 249 | attributes, 250 | namespace 251 | } => { 252 | let mut output: Vec = Vec::new(); 253 | let conf = xml::writer::EmitterConfig::new() 254 | .perform_indent(false) 255 | .write_document_declaration(false) 256 | .normalize_empty_elements(true) 257 | .cdata_to_characters(false) 258 | .keep_element_names_stack(false) 259 | .pad_self_closing(false); 260 | let mut writer = conf.create_writer(&mut output); 261 | writer.write(xml::writer::XmlEvent::StartElement { 262 | name: name.borrow(), 263 | attributes: attributes.iter().map(|a| a.borrow()).collect(), 264 | namespace: std::borrow::Cow::Borrowed(&namespace), 265 | }).unwrap(); 266 | let depth = this.depth - 1; 267 | loop { 268 | let event = this.next()?; 269 | trace!("{:?}; {}; {}", event, this.depth, depth); 270 | if this.depth == depth { 271 | break; 272 | } 273 | if let Some(e) = event.as_writer_event() { 274 | trace!("{:?}; {}; {}", event, this.depth, depth); 275 | writer.write(e).unwrap(); 276 | } 277 | } 278 | writer.write(xml::writer::XmlEvent::EndElement { 279 | name: Some(name.borrow()) 280 | }).unwrap(); 281 | Ok(String::from_utf8(output).unwrap()) 282 | } 283 | _ => Err(crate::Error::ExpectedString) 284 | } 285 | }) 286 | } 287 | 288 | fn parse_bool(&mut self) -> crate::Result { 289 | let s = self.parse_string()?; 290 | match s.to_lowercase().as_str() { 291 | "true" | "1" | "y" => Ok(true), 292 | "false" | "0" | "n" => Ok(false), 293 | _ => Err(crate::Error::ExpectedBool) 294 | } 295 | } 296 | 297 | fn parse_int + MulAssign + std::str::FromStr>(&mut self) -> crate::Result { 298 | let s = self.parse_string()?; 299 | match s.parse::() { 300 | Ok(i) => Ok(i), 301 | Err(_) => Err(crate::Error::ExpectedInt) 302 | } 303 | } 304 | } 305 | 306 | impl<'de, 'a, I: Iterator> de::Deserializer<'de> for &'a mut Deserializer { 307 | type Error = crate::Error; 308 | 309 | fn deserialize_any>(self, visitor: V) -> crate::Result { 310 | trace!("deserialize_any()"); 311 | if let xml::reader::XmlEvent::CData(_) | xml::reader::XmlEvent::Characters(_) = self.peek()? { 312 | let s = match self.next()? { 313 | xml::reader::XmlEvent::CData(s) | xml::reader::XmlEvent::Characters(s) => s, 314 | _ => unreachable!() 315 | }; 316 | visitor.visit_string(s) 317 | } else { 318 | self.reset_peek(); 319 | self.read_inner_value_attrs(|this, attrs| { 320 | visitor.visit_map(Map::new(this, attrs, &[])) 321 | }) 322 | } 323 | // self.peek(); 324 | // Err(crate::Error::Unsupported) 325 | } 326 | 327 | fn deserialize_bool>(self, visitor: V) -> crate::Result { 328 | visitor.visit_bool(self.parse_bool()?) 329 | } 330 | 331 | fn deserialize_i8>(self, visitor: V) -> crate::Result { 332 | visitor.visit_i8(self.parse_int()?) 333 | } 334 | 335 | fn deserialize_i16>(self, visitor: V) -> crate::Result { 336 | visitor.visit_i16(self.parse_int()?) 337 | } 338 | 339 | fn deserialize_i32>(self, visitor: V) -> crate::Result { 340 | visitor.visit_i32(self.parse_int()?) 341 | } 342 | 343 | fn deserialize_i64>(self, visitor: V) -> crate::Result { 344 | visitor.visit_i64(self.parse_int()?) 345 | } 346 | 347 | fn deserialize_u8>(self, visitor: V) -> crate::Result { 348 | visitor.visit_u8(self.parse_int()?) 349 | } 350 | 351 | fn deserialize_u16>(self, visitor: V) -> crate::Result { 352 | visitor.visit_u16(self.parse_int()?) 353 | } 354 | 355 | fn deserialize_u32>(self, visitor: V) -> crate::Result { 356 | visitor.visit_u32(self.parse_int()?) 357 | } 358 | 359 | fn deserialize_u64>(self, visitor: V) -> crate::Result { 360 | visitor.visit_u64(self.parse_int()?) 361 | } 362 | 363 | fn deserialize_f32>(self, visitor: V) -> crate::Result { 364 | visitor.visit_u64(self.parse_int()?) 365 | } 366 | 367 | fn deserialize_f64>(self, visitor: V) -> crate::Result { 368 | visitor.visit_u64(self.parse_int()?) 369 | } 370 | 371 | fn deserialize_char>(self, visitor: V) -> crate::Result { 372 | use std::str::FromStr; 373 | 374 | let s = self.parse_string()?; 375 | if s.len() == 1 { 376 | visitor.visit_char(match char::from_str(&s) { 377 | Ok(c) => c, 378 | Err(_) => return Err(crate::Error::ExpectedChar) 379 | }) 380 | } else { 381 | Err(crate::Error::ExpectedChar) 382 | } 383 | } 384 | 385 | fn deserialize_str>(self, visitor: V) -> crate::Result { 386 | visitor.visit_string(self.parse_string()?) 387 | } 388 | 389 | fn deserialize_string>(self, visitor: V) -> crate::Result { 390 | self.deserialize_str(visitor) 391 | } 392 | 393 | fn deserialize_bytes>(self, _visitor: V) -> crate::Result { 394 | trace!("deserialize_bytes()"); 395 | Err(crate::Error::Unsupported) 396 | } 397 | 398 | fn deserialize_byte_buf>(self, _visitor: V) -> crate::Result { 399 | trace!("deserialize_byte_buf()"); 400 | Err(crate::Error::Unsupported) 401 | } 402 | 403 | fn deserialize_option>(self, visitor: V) -> crate::Result { 404 | trace!("deserialize_option()"); 405 | if self.is_map_value { 406 | if let xml::reader::XmlEvent::StartElement { attributes, .. } = self.peek()? { 407 | if !attributes.is_empty() { 408 | self.reset_peek(); 409 | return visitor.visit_some(self); 410 | } 411 | } 412 | } 413 | if let xml::reader::XmlEvent::EndElement { .. } = self.peek()? { 414 | if self.unset_map_value() { 415 | self.next()?; 416 | } 417 | self.next()?; 418 | visitor.visit_none() 419 | } else { 420 | self.reset_peek(); 421 | visitor.visit_some(self) 422 | } 423 | } 424 | 425 | fn deserialize_unit>(self, visitor: V) -> crate::Result { 426 | visitor.visit_unit() 427 | } 428 | 429 | fn deserialize_unit_struct>(self, name: &'static str, visitor: V) -> crate::Result { 430 | trace!("deserialize_unit_struct({:?})", name); 431 | visitor.visit_unit() 432 | } 433 | 434 | fn deserialize_newtype_struct>(self, name: &'static str, visitor: V) -> crate::Result { 435 | trace!("deserialize_newtype_struct({:?})", name); 436 | visitor.visit_newtype_struct(self) 437 | } 438 | 439 | fn deserialize_seq>(mut self, visitor: V) -> crate::Result { 440 | trace!("deserialize_seq()"); 441 | visitor.visit_seq(Seq::new(&mut self)?) 442 | } 443 | 444 | fn deserialize_tuple>(self, len: usize, visitor: V) -> crate::Result { 445 | trace!("deserialize_tuple({:?})", len); 446 | self.deserialize_seq(visitor) 447 | } 448 | 449 | fn deserialize_tuple_struct>(self, name: &'static str, len: usize, visitor: V) -> crate::Result { 450 | trace!("deserialize_tuple_struct({:?}, {:?})", name, len); 451 | self.deserialize_seq(visitor) 452 | } 453 | 454 | fn deserialize_map>(self, visitor: V) -> crate::Result { 455 | trace!("deserialize_map()"); 456 | self.read_inner_value_attrs(|this, attrs| { 457 | visitor.visit_map(Map::new(this, attrs, &[])) 458 | }) 459 | } 460 | 461 | fn deserialize_struct>(self, name: &'static str, fields: &'static [&'static str], visitor: V) -> crate::Result { 462 | trace!("deserialize_struct({:?}, {:?})", name, fields); 463 | self.read_inner_value_attrs(|this, attrs| { 464 | visitor.visit_map(Map::new(this, attrs, fields)) 465 | }) 466 | } 467 | 468 | fn deserialize_enum>(self, name: &'static str, variants: &'static [&'static str], visitor: V) -> crate::Result { 469 | trace!("deserialize_enum({:?}, {:?})", name, variants); 470 | if self.unset_is_value() { 471 | visitor.visit_enum(Enum::new(self, variants)) 472 | } else { 473 | self.read_inner_value(|this| { 474 | visitor.visit_enum(Enum::new(this, variants)) 475 | }) 476 | } 477 | } 478 | 479 | fn deserialize_identifier>(self, visitor: V) -> crate::Result { 480 | trace!("deserialize_identifier()"); 481 | self.deserialize_str(visitor) 482 | } 483 | 484 | fn deserialize_ignored_any>(self, visitor: V) -> crate::Result { 485 | trace!("deserialize_ignored_any()"); 486 | if self.is_greedy { 487 | let depth = self.depth; 488 | loop { 489 | self.next()?; 490 | if self.depth == depth { 491 | break; 492 | } 493 | } 494 | } else { 495 | let mut depth = 0; 496 | loop { 497 | let next = self.peek()?; 498 | match next { 499 | xml::reader::XmlEvent::StartElement { .. } => { 500 | depth += 1; 501 | } 502 | xml::reader::XmlEvent::EndElement { .. } => { 503 | depth -= 1; 504 | } 505 | _ => {} 506 | } 507 | self.reset_peek_offset += 1; 508 | if depth == 0 { 509 | break; 510 | } 511 | } 512 | } 513 | visitor.visit_unit() 514 | } 515 | } 516 | 517 | struct Seq<'a, I: Iterator> { 518 | de: &'a mut Deserializer, 519 | expected_name: Option, 520 | } 521 | 522 | impl<'a, I: Iterator> Seq<'a, I> { 523 | fn new(de: &'a mut Deserializer) -> crate::Result { 524 | let name = if de.unset_map_value() { 525 | let val = match de.peek()? { 526 | xml::reader::XmlEvent::StartElement { name, .. } => { 527 | Some(name.clone()) 528 | } 529 | _ => return Err(crate::Error::ExpectedElement) 530 | }; 531 | de.reset_peek(); 532 | val 533 | } else { 534 | None 535 | }; 536 | Ok(Self { 537 | de, 538 | expected_name: name, 539 | }) 540 | } 541 | } 542 | 543 | impl<'de, 'a, I: Iterator> de::SeqAccess<'de> for Seq<'a, I> { 544 | type Error = crate::Error; 545 | 546 | fn next_element_seed>(&mut self, seed: T) -> crate::Result> { 547 | trace!("next_element_seed()"); 548 | let more = match (self.de.peek()?, self.expected_name.as_ref()) { 549 | (xml::reader::XmlEvent::StartElement { ref name, .. }, Some(expected_name)) => { 550 | name == expected_name 551 | } 552 | (xml::reader::XmlEvent::EndElement { .. }, None) | (_, Some(_)) | (xml::reader::XmlEvent::EndDocument { .. }, _) => false, 553 | (_, None) => true, 554 | }; 555 | self.de.reset_peek(); 556 | if more { 557 | if self.expected_name.is_some() { 558 | self.de.set_map_value(); 559 | } 560 | seed.deserialize(&mut *self.de).map(Some) 561 | } else { 562 | Ok(None) 563 | } 564 | } 565 | } 566 | 567 | struct Fields { 568 | fields: &'static[Field], 569 | inner_value: bool, 570 | num_value: u64, 571 | value_used: u64, 572 | } 573 | 574 | #[derive(Clone)] 575 | struct Field { 576 | namespace: Option<&'static str>, 577 | local_name: &'static str, 578 | name: &'static str, 579 | attr: bool, 580 | } 581 | 582 | impl From<&&'static str> for Field { 583 | fn from(from: &&'static str) -> Self { 584 | let mut attr = false; 585 | let name = if from.starts_with("$attr:") { 586 | attr = true; 587 | &from[6..] 588 | } else { 589 | from 590 | }; 591 | 592 | let Tag{ 593 | e: local_name, 594 | n: namespace, 595 | .. 596 | } = crate::Tag::from_static(name); 597 | 598 | Field { 599 | namespace, 600 | local_name, 601 | name, 602 | attr, 603 | } 604 | } 605 | } 606 | 607 | impl From<&'static [&'static str]> for Fields { 608 | fn from(from: &'static [&'static str]) -> Self { 609 | use once_cell::sync::OnceCell; 610 | use std::sync::Mutex; 611 | use std::collections::btree_map::{BTreeMap,Entry}; 612 | 613 | let (fields, num_value) = { 614 | // Make a single global BTreeMap to act as a cache 615 | static CACHE: OnceCell>> = OnceCell::new(); 616 | let mut cache = CACHE.get_or_init(|| { 617 | Mutex::new(BTreeMap::new()) 618 | }).lock().unwrap(); 619 | 620 | // Look up the pointer address of our &'static [&'static str] in the cache 621 | match cache.entry((*from).as_ptr() as usize) { 622 | Entry::Vacant(e) => { 623 | // Miss 624 | // Convert the str slice into a Vec 625 | let fields: Vec = from.iter().map(|f| f.into()).collect(); 626 | 627 | // Convert the Vec into a &'static [Field] 628 | let fields = Box::leak(fields.into_boxed_slice()); 629 | 630 | // Count how many $value fields we have 631 | let num_value = from.iter().filter(|f| f.starts_with(&"$value")).count() as u64; 632 | 633 | // Add it to the cache 634 | *e.insert((fields, num_value)) 635 | } 636 | Entry::Occupied(e) => { 637 | // Hit 638 | // Use the existing slice and count 639 | *e.get() 640 | } 641 | } 642 | }; 643 | 644 | Fields { 645 | fields, 646 | inner_value: num_value >= 1, 647 | num_value: num_value, 648 | value_used: 0, 649 | } 650 | } 651 | } 652 | 653 | impl Fields { 654 | fn match_field(&mut self, name: &xml::name::OwnedName) -> Cow<'static, str> { 655 | for field in self.fields.iter() { 656 | if field.local_name == name.local_name && field.namespace == name.namespace.as_deref() && !field.attr { 657 | trace!("match_field({:?}) -> {:?}", name, field.name); 658 | return field.name.into(); 659 | } 660 | } 661 | let name_str = if self.inner_value && self.value_used < self.num_value { 662 | self.value_used += 1; 663 | if self.num_value == 1 { 664 | "$value".to_string() 665 | } else { 666 | format!("$value{}", self.value_used) 667 | } 668 | } else { 669 | match &name.namespace { 670 | Some(n) => format!("{{{}}}{}", n, name.local_name), 671 | None => name.local_name.clone() 672 | } 673 | }; 674 | trace!("match_field({:?}) -> {:?}", name, name_str); 675 | name_str.into() 676 | } 677 | 678 | fn match_attr(&self, name: &xml::name::OwnedName) -> Cow<'static, str> { 679 | for field in self.fields.iter() { 680 | if field.local_name == name.local_name && field.namespace == name.namespace.as_deref() && field.attr { 681 | let name_str = format!("$attr:{}", field.name); 682 | trace!("match_attr({:?}) -> {:?}", name, name_str); 683 | return name_str.into(); 684 | } 685 | } 686 | let name_str = match &name.namespace { 687 | Some(n) => format!("{{{}}}{}", n, name.local_name), 688 | None => name.local_name.clone() 689 | }; 690 | let name_str = format!("$attr:{}", name_str); 691 | trace!("match_attr({:?}) -> {:?}", name, name_str); 692 | name_str.into() 693 | } 694 | } 695 | 696 | struct Map<'a, I: Iterator> { 697 | de: &'a mut Deserializer, 698 | attrs: Vec, 699 | fields: Fields, 700 | next_value: Option, 701 | inner_value: bool, 702 | next_is_value: bool, 703 | } 704 | 705 | impl<'a, I: Iterator> Map<'a, I> { 706 | fn new(de: &'a mut Deserializer, attrs: Vec, fields: &'static [&'static str]) -> Self { 707 | Self { 708 | de, 709 | attrs, 710 | fields: fields.into(), 711 | next_value: None, 712 | inner_value: true, 713 | next_is_value: false, 714 | } 715 | } 716 | } 717 | 718 | impl<'de, 'a, I: Iterator> de::MapAccess<'de> for Map<'a, I> { 719 | type Error = crate::Error; 720 | 721 | fn next_key_seed>(&mut self, seed: K) -> crate::Result> { 722 | trace!("next_key_seed(); attrs = {:?}", self.attrs); 723 | match self.attrs.pop() { 724 | Some(xml::attribute::OwnedAttribute { name, value }) => { 725 | let name = self.fields.match_attr(&name); 726 | self.next_value = Some(value); 727 | self.next_is_value = false; 728 | seed.deserialize(name.as_ref().into_deserializer()).map(Some) 729 | } 730 | None => { 731 | let val = match *self.de.peek()? { 732 | xml::reader::XmlEvent::StartElement { 733 | ref name, .. 734 | } => { 735 | let name = self.fields.match_field(name); 736 | self.inner_value = name.starts_with(&"$value"); 737 | self.next_is_value = name.starts_with(&"$value"); 738 | seed.deserialize(name.as_ref().into_deserializer()).map(Some) 739 | } 740 | xml::reader::XmlEvent::Characters(_) | xml::reader::XmlEvent::CData(_) => { 741 | self.next_is_value = true; 742 | seed.deserialize("$value".into_deserializer()).map(Some) 743 | } 744 | _ => Ok(None) 745 | }; 746 | self.de.reset_peek(); 747 | val 748 | } 749 | } 750 | } 751 | 752 | fn next_value_seed>(&mut self, seed: V) -> crate::Result { 753 | trace!("next_value_seed(); next_value = {:?}; next_is_value = {}", self.next_value, self.next_is_value); 754 | match self.next_value.take() { 755 | Some(val) => seed.deserialize(AttrValueDeserializer(val)), 756 | None => { 757 | if !std::mem::replace(&mut self.inner_value, false) { 758 | self.de.set_map_value(); 759 | } 760 | if self.next_is_value { 761 | self.de.set_is_value(); 762 | } 763 | let greedy = self.next_is_value && self.fields.fields.len() > 1; 764 | if greedy { 765 | self.de.set_not_greedy(); 766 | } 767 | let val = seed.deserialize(&mut *self.de)?; 768 | if greedy { 769 | self.de.unset_not_greedy(); 770 | self.de.reset_peek(); 771 | } 772 | Ok(val) 773 | } 774 | } 775 | } 776 | } 777 | 778 | pub struct Enum<'a, I: Iterator> { 779 | de: &'a mut Deserializer, 780 | fields: Fields, 781 | } 782 | 783 | impl<'a, I: Iterator> Enum<'a, I> { 784 | pub fn new(de: &'a mut Deserializer, fields: &'static [&'static str]) -> Self { 785 | Self { 786 | de, 787 | fields: fields.into(), 788 | } 789 | } 790 | } 791 | 792 | impl<'de, 'a, I: Iterator> de::EnumAccess<'de> for Enum<'a, I> { 793 | type Error = crate::Error; 794 | type Variant = Self; 795 | 796 | fn variant_seed>(mut self, seed: V) -> crate::Result<(V::Value, Self::Variant)> { 797 | trace!("variant_seed()"); 798 | let val = match self.de.peek()? { 799 | xml::reader::XmlEvent::StartElement { 800 | name, .. 801 | } => { 802 | let name_str = self.fields.match_field(name); 803 | if !name_str.starts_with(&"$value") { 804 | self.de.set_map_value(); 805 | } 806 | let name_str: serde::de::value::CowStrDeserializer = name_str.into_deserializer(); 807 | Ok(seed.deserialize(name_str)?) 808 | } 809 | xml::reader::XmlEvent::Characters(s) | xml::reader::XmlEvent::CData(s) => { 810 | let name: serde::de::value::StrDeserializer = s.as_str().into_deserializer(); 811 | Ok(seed.deserialize(name)?) 812 | } 813 | _ => Err(crate::Error::ExpectedString) 814 | }?; 815 | self.de.reset_peek(); 816 | Ok((val, self)) 817 | } 818 | } 819 | 820 | impl<'de, 'a, I: Iterator> de::VariantAccess<'de> for Enum<'a, I> { 821 | type Error = crate::Error; 822 | 823 | fn unit_variant(self) -> crate::Result<()> { 824 | trace!("unit_variant()"); 825 | self.de.unset_map_value(); 826 | match self.de.next()? { 827 | xml::reader::XmlEvent::StartElement { 828 | name, attributes, .. 829 | } => if attributes.is_empty() { 830 | self.de.expect_end_element(name) 831 | } else { 832 | Err(crate::Error::ExpectedElement) 833 | }, 834 | xml::reader::XmlEvent::Characters(_) | xml::reader::XmlEvent::CData(_) => Ok(()), 835 | _ => unreachable!() 836 | } 837 | } 838 | 839 | fn newtype_variant_seed>(self, seed: T) -> crate::Result { 840 | trace!("newtype_variant_seed()"); 841 | seed.deserialize(self.de) 842 | } 843 | 844 | fn tuple_variant>(self, len: usize, visitor: V) -> crate::Result { 845 | trace!("tuple_variant({:?})", len); 846 | use serde::de::Deserializer; 847 | self.de.deserialize_tuple(len, visitor) 848 | } 849 | 850 | fn struct_variant>(self, fields: &'static [&'static str], visitor: V) -> crate::Result { 851 | trace!("struct_variant({:?})", fields); 852 | use serde::de::Deserializer; 853 | self.de.deserialize_struct("", fields, visitor) 854 | } 855 | } 856 | 857 | struct AttrValueDeserializer(String); 858 | 859 | macro_rules! deserialize_type_attr { 860 | ($deserialize:ident => $visit:ident) => { 861 | fn $deserialize>(self, visitor: V) -> crate::Result { 862 | visitor.$visit(match self.0.parse() { 863 | Ok(v) => v, 864 | Err(_) => return Err(crate::Error::ExpectedInt) 865 | }) 866 | } 867 | } 868 | } 869 | 870 | impl<'de> serde::de::Deserializer<'de> for AttrValueDeserializer { 871 | type Error = crate::Error; 872 | 873 | fn deserialize_any>(self, visitor: V) -> crate::Result { 874 | visitor.visit_string(self.0) 875 | } 876 | 877 | deserialize_type_attr!(deserialize_i8 => visit_i8); 878 | deserialize_type_attr!(deserialize_i16 => visit_i16); 879 | deserialize_type_attr!(deserialize_i32 => visit_i32); 880 | deserialize_type_attr!(deserialize_i64 => visit_i64); 881 | deserialize_type_attr!(deserialize_u8 => visit_u8); 882 | deserialize_type_attr!(deserialize_u16 => visit_u16); 883 | deserialize_type_attr!(deserialize_u32 => visit_u32); 884 | deserialize_type_attr!(deserialize_u64 => visit_u64); 885 | deserialize_type_attr!(deserialize_f32 => visit_f32); 886 | deserialize_type_attr!(deserialize_f64 => visit_f64); 887 | 888 | fn deserialize_enum>(self, name: &str, variants: &'static [&'static str], visitor: V) -> crate::Result { 889 | trace!("deserialize_enum({:?}, {:?})", name, variants); 890 | visitor.visit_enum(self.0.into_deserializer()) 891 | } 892 | 893 | fn deserialize_option>(self, visitor: V) -> crate::Result { 894 | visitor.visit_some(self) 895 | } 896 | 897 | fn deserialize_bool>(self, visitor: V) -> crate::Result { 898 | match self.0.to_lowercase().as_str() { 899 | "true" | "1" | "y" => visitor.visit_bool(true), 900 | "false" | "0" | "n" => visitor.visit_bool(false), 901 | _ => Err(crate::Error::ExpectedBool), 902 | } 903 | } 904 | 905 | serde::forward_to_deserialize_any! { 906 | char str string unit seq bytes map unit_struct newtype_struct tuple_struct 907 | struct identifier tuple ignored_any byte_buf 908 | } 909 | } 910 | 911 | #[cfg(test)] 912 | mod tests { 913 | #[test] 914 | fn deserialize_element_into_struct() { 915 | #[derive(Debug, PartialEq, Deserialize)] 916 | struct Foo { 917 | #[serde(rename = "{urn:foo}foo:bar")] 918 | bar: String, 919 | } 920 | 921 | assert_eq!( 922 | crate::from_str::( 923 | r#" 924 | 925 | baz 926 | "# 927 | ) 928 | .unwrap(), 929 | Foo { 930 | bar: "baz".to_string() 931 | } 932 | ); 933 | } 934 | 935 | #[test] 936 | fn deserialize_element_with_processing_instruction_into_struct() { 937 | #[derive(Debug, PartialEq, Deserialize)] 938 | struct Foo { 939 | #[serde(rename = "{urn:foo}foo:bar")] 940 | bar: String, 941 | } 942 | 943 | assert_eq!( 944 | crate::from_str::( 945 | r#" 946 | 947 | 948 | baz 949 | "# 950 | ) 951 | .unwrap(), 952 | Foo { 953 | bar: "baz".to_string() 954 | } 955 | ); 956 | } 957 | } 958 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug)] 2 | pub enum Error { 3 | XMLWError(xml::writer::Error), 4 | XMLRError(xml::reader::Error), 5 | Message(String), 6 | ExpectedString, 7 | ExpectedChar, 8 | ExpectedBool, 9 | ExpectedInt, 10 | ExpectedElement, 11 | Unsupported 12 | } 13 | 14 | pub type Result = std::result::Result; 15 | 16 | impl serde::ser::Error for Error { 17 | fn custom(msg: T) -> Self { 18 | Error::Message(msg.to_string()) 19 | } 20 | } 21 | 22 | impl serde::de::Error for Error { 23 | fn custom(msg: T) -> Self { 24 | Error::Message(msg.to_string()) 25 | } 26 | } 27 | 28 | impl std::fmt::Display for Error { 29 | fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { 30 | match self { 31 | Error::Message(msg) => formatter.write_str(msg), 32 | Error::XMLWError(err) => formatter.write_str(&err.to_string()), 33 | Error::XMLRError(err) => formatter.write_str(&err.to_string()), 34 | Error::ExpectedString => formatter.write_str("expected a string"), 35 | Error::ExpectedChar => formatter.write_str("expected a char"), 36 | Error::ExpectedBool => formatter.write_str("expected a bool"), 37 | Error::ExpectedInt => formatter.write_str("expected a number"), 38 | Error::ExpectedElement => formatter.write_str("expected an element"), 39 | Error::Unsupported => formatter.write_str("unsupported operation"), 40 | } 41 | } 42 | } 43 | 44 | impl std::error::Error for Error {} 45 | 46 | impl From for Error { 47 | fn from(err: xml::writer::Error) -> Self { 48 | Error::XMLWError(err) 49 | } 50 | } 51 | 52 | impl From for Error { 53 | fn from(err: xml::reader::Error) -> Self { 54 | Error::XMLRError(err) 55 | } 56 | } 57 | 58 | impl From<&xml::reader::Error> for Error { 59 | fn from(err: &xml::reader::Error) -> Self { 60 | Error::XMLRError(err.clone()) 61 | } 62 | } -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | #[macro_use] 3 | extern crate serde_derive; 4 | #[macro_use] 5 | extern crate log; 6 | extern crate core; 7 | 8 | mod de; 9 | mod ser; 10 | mod error; 11 | mod tag; 12 | 13 | pub(crate) use tag::Tag; 14 | 15 | pub use ser::{to_string, to_string_custom, to_events, to_events_custom, Serializer, Options}; 16 | pub use de::{from_str, from_string, from_events, Deserializer}; 17 | pub use error::{Error, Result}; 18 | 19 | #[cfg(test)] 20 | mod tests { 21 | 22 | #[derive(Debug, Serialize, Deserialize)] 23 | pub enum EPPMessageType { 24 | #[serde(rename = "{urn:ietf:params:xml:ns:epp-1.0}hello", skip_deserializing)] 25 | Hello {}, 26 | // #[serde(rename = "{urn:ietf:params:xml:ns:epp-1.0}greeting", skip_serializing)] 27 | // Greeting(EPPGreeting), 28 | #[serde(rename = "{urn:ietf:params:xml:ns:epp-1.0}command", skip_deserializing)] 29 | Command(EPPCommand), 30 | // #[serde(rename = "{urn:ietf:params:xml:ns:epp-1.0}response", skip_serializing)] 31 | // Response(EPPResponse), 32 | } 33 | 34 | #[derive(Debug, Serialize, Deserialize)] 35 | pub struct EPPMessage { 36 | #[serde(rename = "{urn:ietf:params:xml:ns:epp-1.0}epp")] 37 | pub message: EPPMessageType, 38 | } 39 | 40 | 41 | #[derive(Debug, Serialize)] 42 | pub struct EPPCommand { 43 | #[serde(rename = "$valueRaw")] 44 | pub command: String, 45 | #[serde(rename = "{urn:ietf:params:xml:ns:epp-1.0}clTRID", skip_serializing_if = "Option::is_none")] 46 | pub client_transaction_id: Option, 47 | } 48 | 49 | #[derive(Debug, Serialize)] 50 | pub enum EPPCommandType { 51 | #[serde(rename = "{urn:ietf:params:xml:ns:epp-1.0}login")] 52 | Login(EPPLogin), 53 | } 54 | 55 | #[derive(Debug, Serialize)] 56 | pub struct EPPLogin { 57 | #[serde(rename = "{urn:ietf:params:xml:ns:epp-1.0}clID")] 58 | pub client_id: String, 59 | #[serde(rename = "{urn:ietf:params:xml:ns:epp-1.0}pw")] 60 | pub password: String, 61 | #[serde(rename = "$attr:{http://www.w3.org/2001/XMLSchema-instance}newPW", skip_serializing_if = "Option::is_none")] 62 | pub new_password: Option, 63 | pub options: EPPLoginOptions, 64 | #[serde(rename = "{urn:ietf:params:xml:ns:epp-1.0}svcs")] 65 | pub services: EPPLoginServices, 66 | } 67 | 68 | #[derive(Debug, Serialize)] 69 | pub struct EPPLoginOptions { 70 | pub version: String, 71 | #[serde(rename = "{urn:ietf:params:xml:ns:epp-1.0}lang")] 72 | pub language: String, 73 | } 74 | 75 | #[derive(Debug, Serialize)] 76 | pub struct EPPLoginServices { 77 | #[serde(rename = "{urn:ietf:params:xml:ns:epp-1.0}objURI")] 78 | pub objects: Vec, 79 | } 80 | 81 | 82 | #[test] 83 | fn encode() { 84 | pretty_env_logger::init(); 85 | println!("{:?}", super::ser::to_string(&EPPMessage { 86 | message: EPPMessageType::Command(EPPCommand { 87 | command: "&".to_string(), 88 | client_transaction_id: Some("&".to_string()), 89 | }) 90 | }).unwrap()); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/ser.rs: -------------------------------------------------------------------------------- 1 | //! Custom serde XML serializer 2 | //! 3 | //! The special serde tag name `$value` equates to the inner value of an XML element. 4 | //! Tags starting with `$attr:` will be encoded as attributes rather than new elements. 5 | //! Namespaces and prefixes can be set using the tag name format `{namespace}prefix:tag-name`. 6 | 7 | use std::borrow::Cow; 8 | use serde::{ser, Serialize}; 9 | use crate::Tag; 10 | 11 | pub struct Serializer; 12 | 13 | trait EventWriter { 14 | fn write<'a, E: Into>>(&mut self, event: E) -> xml::writer::Result<()>; 15 | } 16 | 17 | struct EmitterWriter(xml::writer::EventWriter); 18 | 19 | impl EventWriter for EmitterWriter { 20 | fn write<'a, E: Into>>(&mut self, event: E) -> xml::writer::Result<()> { 21 | self.0.write(event) 22 | } 23 | } 24 | 25 | struct ListWriter(Vec); 26 | 27 | impl EventWriter for ListWriter { 28 | fn write<'a, E: Into>>(&mut self, event: E) -> xml::writer::Result<()> { 29 | let e = event.into(); 30 | let re = match e { 31 | xml::writer::XmlEvent::StartDocument { version, encoding, standalone } => { 32 | xml::reader::XmlEvent::StartDocument { 33 | version, 34 | encoding: encoding.unwrap_or("UTF-8").to_string(), 35 | standalone, 36 | } 37 | } 38 | xml::writer::XmlEvent::ProcessingInstruction { name, data } => { 39 | xml::reader::XmlEvent::ProcessingInstruction { 40 | name: name.to_string(), 41 | data: data.map(Into::into), 42 | } 43 | } 44 | xml::writer::XmlEvent::StartElement { name, attributes, namespace } => { 45 | xml::reader::XmlEvent::StartElement { 46 | name: name.to_owned(), 47 | attributes: (*attributes).iter().map(|a| a.to_owned()).collect(), 48 | namespace: (*namespace).clone(), 49 | } 50 | } 51 | xml::writer::XmlEvent::EndElement { name } => { 52 | xml::reader::XmlEvent::EndElement { 53 | name: match name { 54 | Some(n) => n.to_owned(), 55 | None => unreachable!() 56 | }, 57 | } 58 | } 59 | xml::writer::XmlEvent::CData(s) => { 60 | xml::reader::XmlEvent::CData(s.into()) 61 | } 62 | xml::writer::XmlEvent::Characters(s) => { 63 | xml::reader::XmlEvent::Characters(s.into()) 64 | } 65 | xml::writer::XmlEvent::Comment(s) => { 66 | xml::reader::XmlEvent::Comment(s.into()) 67 | } 68 | }; 69 | self.0.push(re); 70 | Ok(()) 71 | } 72 | } 73 | 74 | pub struct Options { 75 | pub include_schema_location: bool 76 | } 77 | 78 | impl Default for Options { 79 | fn default() -> Self { 80 | Self { 81 | include_schema_location: true 82 | } 83 | } 84 | } 85 | 86 | /// Serialise serde item to XML 87 | /// 88 | /// # Arguments 89 | /// * `value` - The value to be serialised 90 | pub fn to_string(value: &T) -> Result 91 | where 92 | T: Serialize, 93 | { 94 | to_string_custom(value, Options::default()) 95 | } 96 | 97 | /// Serialise serde item to XML, with custom options 98 | /// 99 | /// # Arguments 100 | /// * `value` - The value to be serialised 101 | /// * `options` - Custom options for the serializer 102 | pub fn to_string_custom(value: &T, options: Options) -> Result 103 | where 104 | T: Serialize, 105 | { 106 | let mut conf = xml::writer::EmitterConfig::new() 107 | .perform_indent(true) 108 | .write_document_declaration(true) 109 | .normalize_empty_elements(true) 110 | .cdata_to_characters(true) 111 | .keep_element_names_stack(true) 112 | .pad_self_closing(false); 113 | conf.perform_escaping = false; 114 | 115 | let c = std::io::Cursor::new(Vec::new()); 116 | let mut writer = EmitterWriter(conf.create_writer(c)); 117 | let mut serializer = Serializer; 118 | let val = value.serialize(&mut serializer)?; 119 | let mut state = _SerializerState { 120 | raw_output: false, 121 | ns_stack: vec![], 122 | include_schema_location: options.include_schema_location, 123 | }; 124 | format_data(&mut writer, &val, &mut state)?; 125 | Ok(String::from_utf8(writer.0.into_inner().into_inner()).unwrap()) 126 | } 127 | 128 | /// Serialise serde item to a list of XML events 129 | /// 130 | /// # Arguments 131 | /// * `value` - The value to be serialised 132 | pub fn to_events(value: &T) -> Result, crate::Error> 133 | where 134 | T: Serialize, 135 | { 136 | to_events_custom(value, Options::default()) 137 | } 138 | 139 | /// Serialise serde item to a list of XML events, with custom options 140 | /// 141 | /// # Arguments 142 | /// * `value` - The value to be serialised 143 | /// * `options` - Custom options for the serializer 144 | pub fn to_events_custom(value: &T, options: Options) -> Result, crate::Error> 145 | where 146 | T: Serialize, 147 | { 148 | let mut writer = ListWriter(vec![]); 149 | let mut serializer = Serializer; 150 | let val = value.serialize(&mut serializer)?; 151 | let mut state = _SerializerState { 152 | raw_output: false, 153 | ns_stack: vec![], 154 | include_schema_location: options.include_schema_location, 155 | }; 156 | format_data(&mut writer, &val, &mut state)?; 157 | Ok(writer.0) 158 | } 159 | 160 | #[derive(Debug)] 161 | pub enum _SerializerData { 162 | CData(String), 163 | String(String), 164 | Seq(Vec<_SerializerData>), 165 | Struct { attrs: Vec<(Cow<'static, str>, String)>, contents: Vec<(Cow<'static, str>, _SerializerData)> }, 166 | } 167 | 168 | impl _SerializerData { 169 | fn as_str(&self) -> String { 170 | match self { 171 | _SerializerData::CData(s) => s.clone(), 172 | _SerializerData::String(s) => s.clone(), 173 | _SerializerData::Seq(s) => s.iter().map(|d| d.as_str()).collect::>().join(","), 174 | _SerializerData::Struct { contents, .. } => contents.iter().map(|(_, d)| d.as_str()).collect::>().join(","), 175 | } 176 | } 177 | } 178 | 179 | struct _SerializerState { 180 | raw_output: bool, 181 | ns_stack: Vec, 182 | include_schema_location: bool, 183 | } 184 | 185 | fn format_data(writer: &mut W, val: &_SerializerData, state: &mut _SerializerState) -> Result<(), crate::Error> { 186 | match val { 187 | _SerializerData::CData(s) => { 188 | writer.write(xml::writer::XmlEvent::cdata(&match state.raw_output { 189 | true => s.to_string(), 190 | false => xml::escape::escape_str_pcdata(s).to_string() 191 | }))? 192 | } 193 | _SerializerData::String(s) => { 194 | writer.write(xml::writer::XmlEvent::characters(&match state.raw_output { 195 | true => s.to_string(), 196 | false => xml::escape::escape_str_pcdata(s).to_string() 197 | }))? 198 | } 199 | _SerializerData::Seq(s) => { 200 | for d in s { 201 | format_data(writer, &d, state)?; 202 | } 203 | } 204 | _SerializerData::Struct { 205 | contents, 206 | .. 207 | } => { 208 | for (tag, d) in contents { 209 | if *tag == "$valueRaw" { 210 | let old_val = state.raw_output; 211 | state.raw_output = true; 212 | format_data(writer, &d, state)?; 213 | state.raw_output = old_val; 214 | } else if tag.starts_with(&"$value") { 215 | format_data(writer, &d, state)?; 216 | } else { 217 | let parsed_tag = Tag::from_cow(&tag); 218 | let base_name = parsed_tag.e; 219 | let name = match parsed_tag.p { 220 | Some(p) => format!("{}:{}", p, base_name), 221 | None => base_name.to_string() 222 | }; 223 | 224 | match d { 225 | _SerializerData::Seq(s) => { 226 | for d in s { 227 | let attrs = match d { 228 | _SerializerData::Struct { 229 | attrs, 230 | .. 231 | } => attrs.to_owned(), 232 | _ => vec![] 233 | }; 234 | let attrs = attrs.iter().map(|(attr_k, attr_v)| { 235 | (xml::name::Name::from(Tag::from_cow(attr_k)), attr_v) 236 | }).collect::>(); 237 | let mut elm = xml::writer::XmlEvent::start_element(name.as_str()); 238 | if state.include_schema_location { 239 | elm = elm.ns("xsi", "http://www.w3.org/2001/XMLSchema-instance"); 240 | } 241 | let mut loc = String::new(); 242 | let mut should_pop = false; 243 | if let Some(n) = parsed_tag.n { 244 | match parsed_tag.p { 245 | Some(p) => elm = elm.ns(p, n), 246 | None => elm = elm.default_ns(n) 247 | }; 248 | if !state.ns_stack.iter().any(|ns| ns == n) { 249 | if let Some(l) = parsed_tag.l { 250 | if !l.is_empty() { 251 | loc.push_str(&format!("{} {}", n, l)); 252 | } 253 | } else { 254 | let last_n = n.rsplit(':').next().unwrap(); 255 | loc.push_str(&format!("{} {}.xsd", n, last_n)); 256 | } 257 | if state.include_schema_location && !loc.is_empty() { 258 | elm = elm.attr(xml::name::Name { 259 | namespace: None, 260 | local_name: "schemaLocation", 261 | prefix: Some("xsi"), 262 | }, &loc); 263 | } 264 | state.ns_stack.push(n.to_string()); 265 | should_pop = true; 266 | } 267 | } 268 | for (name, attr_v) in attrs.clone() { 269 | elm = elm.attr(name, attr_v); 270 | } 271 | 272 | writer.write(elm)?; 273 | format_data(writer, &d, state)?; 274 | writer.write(xml::writer::XmlEvent::end_element())?; 275 | if should_pop { 276 | state.ns_stack.pop(); 277 | } 278 | } 279 | } 280 | d => { 281 | let attrs = match d { 282 | _SerializerData::Struct { 283 | attrs, 284 | .. 285 | } => attrs.to_owned(), 286 | _ => vec![] 287 | }; 288 | let attrs = attrs.iter().map(|(attr_k, attr_v)| { 289 | (xml::name::Name::from(Tag::from_cow(attr_k)), attr_v) 290 | }).collect::>(); 291 | 292 | let mut elm = xml::writer::XmlEvent::start_element(name.as_str()); 293 | if state.include_schema_location { 294 | elm = elm.ns("xsi", "http://www.w3.org/2001/XMLSchema-instance"); 295 | } 296 | let mut loc = String::new(); 297 | let mut should_pop = false; 298 | if let Some(n) = parsed_tag.n { 299 | match parsed_tag.p { 300 | Some(p) => elm = elm.ns(p, n), 301 | None => elm = elm.default_ns(n) 302 | }; 303 | if !state.ns_stack.iter().any(|ns| ns == n) { 304 | if let Some(l) = parsed_tag.l { 305 | if !l.is_empty() { 306 | loc.push_str(&format!("{} {}", n, l)); 307 | } 308 | } else { 309 | let last_n = n.rsplit(':').next().unwrap(); 310 | loc.push_str(&format!("{} {}.xsd", n, last_n)); 311 | } 312 | if state.include_schema_location && !loc.is_empty() { 313 | elm = elm.attr(xml::name::Name { 314 | namespace: None, 315 | local_name: "schemaLocation", 316 | prefix: Some("xsi"), 317 | }, &loc); 318 | } 319 | state.ns_stack.push(n.to_string()); 320 | should_pop = true; 321 | } 322 | } 323 | for (name, attr_v) in attrs { 324 | elm = elm.attr(name, attr_v); 325 | } 326 | 327 | writer.write(elm)?; 328 | format_data(writer, &d, state)?; 329 | writer.write(xml::writer::XmlEvent::end_element())?; 330 | if should_pop { 331 | state.ns_stack.pop(); 332 | } 333 | } 334 | }; 335 | } 336 | } 337 | } 338 | } 339 | Ok(()) 340 | } 341 | 342 | impl<'a> ser::Serializer for &'a mut Serializer { 343 | type Ok = _SerializerData; 344 | type Error = crate::Error; 345 | type SerializeSeq = SeqSerializer<'a>; 346 | type SerializeTuple = SeqSerializer<'a>; 347 | type SerializeTupleStruct = SeqSerializer<'a, >; 348 | type SerializeTupleVariant = SeqSerializer<'a>; 349 | type SerializeMap = MapSerializer<'a>; 350 | type SerializeStruct = StructSerializer<'a>; 351 | type SerializeStructVariant = StructVariantSerializer<'a>; 352 | 353 | fn serialize_bool(self, v: bool) -> Result<_SerializerData, Self::Error> { 354 | let val = if v { "true" } else { "false" }; 355 | Ok(_SerializerData::String(val.to_string())) 356 | } 357 | 358 | fn serialize_i8(self, v: i8) -> Result<_SerializerData, Self::Error> { 359 | self.serialize_i64(i64::from(v)) 360 | } 361 | 362 | fn serialize_i16(self, v: i16) -> Result<_SerializerData, Self::Error> { 363 | self.serialize_i64(i64::from(v)) 364 | } 365 | 366 | fn serialize_i32(self, v: i32) -> Result<_SerializerData, Self::Error> { 367 | self.serialize_i64(i64::from(v)) 368 | } 369 | 370 | fn serialize_i64(self, v: i64) -> Result<_SerializerData, Self::Error> { 371 | Ok(_SerializerData::String(v.to_string())) 372 | } 373 | 374 | fn serialize_u8(self, v: u8) -> Result<_SerializerData, Self::Error> { 375 | self.serialize_u64(u64::from(v)) 376 | } 377 | 378 | fn serialize_u16(self, v: u16) -> Result<_SerializerData, Self::Error> { 379 | self.serialize_u64(u64::from(v)) 380 | } 381 | 382 | fn serialize_u32(self, v: u32) -> Result<_SerializerData, Self::Error> { 383 | self.serialize_u64(u64::from(v)) 384 | } 385 | 386 | fn serialize_u64(self, v: u64) -> Result<_SerializerData, Self::Error> { 387 | Ok(_SerializerData::String(v.to_string())) 388 | } 389 | 390 | fn serialize_f32(self, v: f32) -> Result<_SerializerData, Self::Error> { 391 | self.serialize_f64(f64::from(v)) 392 | } 393 | 394 | fn serialize_f64(self, v: f64) -> Result<_SerializerData, Self::Error> { 395 | Ok(_SerializerData::String(v.to_string())) 396 | } 397 | 398 | fn serialize_char(self, v: char) -> Result<_SerializerData, Self::Error> { 399 | self.serialize_str(&v.to_string()) 400 | } 401 | 402 | fn serialize_str(self, v: &str) -> Result<_SerializerData, Self::Error> { 403 | Ok(_SerializerData::CData(v.to_string())) 404 | } 405 | 406 | fn serialize_bytes(self, v: &[u8]) -> Result<_SerializerData, Self::Error> { 407 | Ok(_SerializerData::String(hex::encode(v))) 408 | } 409 | 410 | fn serialize_none(self) -> Result<_SerializerData, Self::Error> { 411 | Ok(_SerializerData::String("".to_string())) 412 | } 413 | 414 | fn serialize_some(self, value: &T) -> Result<_SerializerData, Self::Error> 415 | where 416 | T: ?Sized + Serialize, 417 | { 418 | value.serialize(self) 419 | } 420 | 421 | fn serialize_unit(self) -> Result<_SerializerData, Self::Error> { 422 | self.serialize_none() 423 | } 424 | 425 | fn serialize_unit_struct(self, _name: &'static str) -> Result<_SerializerData, Self::Error> { 426 | self.serialize_unit() 427 | } 428 | 429 | fn serialize_unit_variant( 430 | self, 431 | _name: &'static str, 432 | _variant_index: u32, 433 | variant: &'static str, 434 | ) -> Result<_SerializerData, Self::Error> { 435 | self.serialize_str(variant) 436 | } 437 | 438 | fn serialize_newtype_struct( 439 | self, 440 | _name: &'static str, 441 | value: &T, 442 | ) -> Result<_SerializerData, Self::Error> 443 | where 444 | T: ?Sized + Serialize, 445 | { 446 | value.serialize(self) 447 | } 448 | 449 | fn serialize_newtype_variant( 450 | self, 451 | _name: &'static str, 452 | _variant_index: u32, 453 | variant: &'static str, 454 | value: &T, 455 | ) -> Result<_SerializerData, Self::Error> 456 | where 457 | T: ?Sized + Serialize, 458 | { 459 | let value = value.serialize(&mut *self)?; 460 | Ok(_SerializerData::Struct { 461 | attrs: vec![], 462 | contents: vec![(variant.into(), value)], 463 | }) 464 | } 465 | 466 | fn serialize_seq(self, _len: Option) -> Result { 467 | Ok(SeqSerializer { 468 | parent: self, 469 | output: vec![], 470 | }) 471 | } 472 | 473 | fn serialize_tuple(self, len: usize) -> Result { 474 | self.serialize_seq(Some(len)) 475 | } 476 | 477 | fn serialize_tuple_struct( 478 | self, 479 | _name: &'static str, 480 | len: usize, 481 | ) -> Result { 482 | self.serialize_seq(Some(len)) 483 | } 484 | 485 | fn serialize_tuple_variant( 486 | self, 487 | _name: &'static str, 488 | _variant_index: u32, 489 | _variant: &'static str, 490 | len: usize, 491 | ) -> Result { 492 | self.serialize_seq(Some(len)) 493 | } 494 | 495 | fn serialize_map(self, _len: Option) -> Result { 496 | Ok(MapSerializer { 497 | parent: self, 498 | keys: vec![], 499 | cur_key: String::new(), 500 | }) 501 | } 502 | 503 | fn serialize_struct( 504 | self, 505 | _name: &'static str, 506 | _len: usize, 507 | ) -> Result { 508 | Ok(StructSerializer { 509 | parent: self, 510 | attrs: vec![], 511 | keys: vec![], 512 | }) 513 | } 514 | 515 | fn serialize_struct_variant( 516 | self, 517 | _name: &'static str, 518 | _variant_index: u32, 519 | variant: &'static str, 520 | _len: usize, 521 | ) -> Result { 522 | Ok(StructVariantSerializer { 523 | parent: self, 524 | attrs: vec![], 525 | keys: vec![], 526 | tag: variant.to_string(), 527 | }) 528 | } 529 | } 530 | 531 | pub struct SeqSerializer<'a> { 532 | parent: &'a mut Serializer, 533 | output: Vec<_SerializerData>, 534 | } 535 | 536 | impl<'a> ser::SerializeSeq for SeqSerializer<'a> { 537 | type Ok = _SerializerData; 538 | type Error = crate::Error; 539 | 540 | fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> 541 | where 542 | T: ?Sized + Serialize, 543 | { 544 | let val = value.serialize(&mut *self.parent)?; 545 | self.output.push(val); 546 | Ok(()) 547 | } 548 | 549 | fn end(self) -> Result<_SerializerData, Self::Error> { 550 | Ok(_SerializerData::Seq(self.output)) 551 | } 552 | } 553 | 554 | impl<'a> ser::SerializeTuple for SeqSerializer<'a> { 555 | type Ok = _SerializerData; 556 | type Error = crate::Error; 557 | 558 | fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> 559 | where 560 | T: ?Sized + Serialize, 561 | { 562 | let val = value.serialize(&mut *self.parent)?; 563 | self.output.push(val); 564 | Ok(()) 565 | } 566 | 567 | fn end(self) -> Result<_SerializerData, Self::Error> { 568 | Ok(_SerializerData::Seq(self.output)) 569 | } 570 | } 571 | 572 | impl<'a> ser::SerializeTupleStruct for SeqSerializer<'a> { 573 | type Ok = _SerializerData; 574 | type Error = crate::Error; 575 | 576 | fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> 577 | where 578 | T: ?Sized + Serialize, 579 | { 580 | let val = value.serialize(&mut *self.parent)?; 581 | self.output.push(val); 582 | Ok(()) 583 | } 584 | 585 | fn end(self) -> Result<_SerializerData, Self::Error> { 586 | Ok(_SerializerData::Seq(self.output)) 587 | } 588 | } 589 | 590 | impl<'a> ser::SerializeTupleVariant for SeqSerializer<'a> { 591 | type Ok = _SerializerData; 592 | type Error = crate::Error; 593 | 594 | fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> 595 | where 596 | T: ?Sized + Serialize, 597 | { 598 | let val = value.serialize(&mut *self.parent)?; 599 | self.output.push(val); 600 | Ok(()) 601 | } 602 | 603 | fn end(self) -> Result<_SerializerData, Self::Error> { 604 | Ok(_SerializerData::Seq(self.output)) 605 | } 606 | } 607 | 608 | pub struct MapSerializer<'a> { 609 | parent: &'a mut Serializer, 610 | keys: Vec<(Cow<'static, str>, _SerializerData)>, 611 | cur_key: String, 612 | } 613 | 614 | impl<'a> ser::SerializeMap for MapSerializer<'a> { 615 | type Ok = _SerializerData; 616 | type Error = crate::Error; 617 | 618 | fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> 619 | where 620 | T: ?Sized + Serialize, 621 | { 622 | let val = key.serialize(&mut *self.parent)?; 623 | self.cur_key = val.as_str(); 624 | Ok(()) 625 | } 626 | 627 | fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> 628 | where 629 | T: ?Sized + Serialize, 630 | { 631 | let val = value.serialize(&mut *self.parent)?; 632 | self.keys.push((self.cur_key.clone().into(), val)); 633 | Ok(()) 634 | } 635 | 636 | fn end(self) -> Result<_SerializerData, Self::Error> { 637 | Ok(_SerializerData::Struct { 638 | attrs: vec![], 639 | contents: self.keys.into_iter().map(|(k,v)| (Cow::from(k), v)).collect(), 640 | }) 641 | } 642 | } 643 | 644 | pub struct StructSerializer<'a> { 645 | parent: &'a mut Serializer, 646 | attrs: Vec<(&'static str, String)>, 647 | keys: Vec<(&'static str, _SerializerData)>, 648 | } 649 | 650 | impl<'a> ser::SerializeStruct for StructSerializer<'a> { 651 | type Ok = _SerializerData; 652 | type Error = crate::Error; 653 | 654 | fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> 655 | where 656 | T: ?Sized + Serialize, 657 | { 658 | let val = value.serialize(&mut *self.parent)?; 659 | if key.starts_with("$attr:") { 660 | self.attrs.push((&key[6..], val.as_str())); 661 | } else { 662 | self.keys.push((key, val)); 663 | } 664 | Ok(()) 665 | } 666 | 667 | fn end(self) -> Result<_SerializerData, Self::Error> { 668 | Ok(_SerializerData::Struct { 669 | attrs: self.attrs.into_iter().map(|(k,v)| (k.into(), v)).collect(), 670 | contents: self.keys.into_iter().map(|(k,v)| (k.into(), v)).collect(), 671 | }) 672 | } 673 | } 674 | 675 | pub struct StructVariantSerializer<'a> { 676 | parent: &'a mut Serializer, 677 | attrs: Vec<(Cow<'static, str>, String)>, 678 | keys: Vec<(Cow<'static, str>, _SerializerData)>, 679 | tag: String, 680 | } 681 | 682 | impl<'a> ser::SerializeStructVariant for StructVariantSerializer<'a> { 683 | type Ok = _SerializerData; 684 | type Error = crate::Error; 685 | 686 | fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> 687 | where 688 | T: ?Sized + Serialize, 689 | { 690 | let val = value.serialize(&mut *self.parent)?; 691 | if key.starts_with("$attr:") { 692 | self.attrs.push((key[6..].into(), val.as_str())); 693 | } else { 694 | self.keys.push((key.into(), val)); 695 | } 696 | Ok(()) 697 | } 698 | 699 | fn end(self) -> Result<_SerializerData, Self::Error> { 700 | Ok(_SerializerData::Struct { 701 | attrs: vec![], 702 | contents: vec![(self.tag.into(), _SerializerData::Struct { 703 | attrs: self.attrs, 704 | contents: self.keys, 705 | })], 706 | }) 707 | } 708 | } 709 | -------------------------------------------------------------------------------- /src/tag.rs: -------------------------------------------------------------------------------- 1 | use std::borrow::Cow; 2 | 3 | static NAME_RE: once_cell::sync::Lazy = once_cell::sync::Lazy::new(|| { 4 | regex::Regex::new(r"^(?:\{(?P[^;]+)(?:;(?P.*))?\})?(?:(?P

.+):)?(?P.+)$").unwrap() 5 | }); 6 | 7 | #[derive(Debug,Copy,Clone,Eq,PartialEq)] 8 | pub(crate) struct Tag<'a> { 9 | pub n: Option<&'a str>, 10 | pub l: Option<&'a str>, 11 | pub p: Option<&'a str>, 12 | pub e: &'a str, 13 | } 14 | 15 | impl<'a> Tag<'a> { 16 | pub fn new(str: &'a str) -> Self { 17 | let captures = NAME_RE.captures(str).unwrap(); 18 | Self { 19 | n: captures.name("n").map(|m| m.as_str()), 20 | l: captures.name("l").map(|m| m.as_str()), 21 | p: captures.name("p").map(|m| m.as_str()), 22 | e: captures.name("e").map(|m| m.as_str()).unwrap(), 23 | } 24 | } 25 | 26 | pub fn from_cow(str: &'a Cow<'static, str>) -> Tag<'a> { 27 | match str { 28 | Cow::Borrowed(str) => Tag::from_static(str), 29 | Cow::Owned(str) => Self::new(str.as_ref()), 30 | } 31 | } 32 | } 33 | 34 | impl Tag<'static> { 35 | pub fn from_static(str: &'static str) -> Tag<'static> { 36 | use once_cell::sync::OnceCell; 37 | use std::sync::Mutex; 38 | use std::collections::btree_map::{BTreeMap,Entry}; 39 | 40 | // Make a single global BTreeMap to act as a cache 41 | static CACHE: OnceCell>>> = OnceCell::new(); 42 | let mut cache = CACHE.get_or_init(|| { 43 | Mutex::new(BTreeMap::new()) 44 | }).lock().unwrap(); 45 | 46 | // Look up the pointer address of our &'static [&'static str] in the cache 47 | match cache.entry(str.as_ptr() as usize) { 48 | Entry::Vacant(e) => { 49 | // Miss 50 | *e.insert(Self::new(str)) 51 | } 52 | Entry::Occupied(e) => { 53 | // Hit 54 | *e.get() 55 | } 56 | } 57 | } 58 | } 59 | 60 | impl<'a> From> for xml::name::Name<'a> { 61 | fn from(tag: Tag<'a>) -> Self { 62 | xml::name::Name { 63 | local_name: tag.e, 64 | namespace: tag.n, 65 | prefix: tag.p, 66 | } 67 | } 68 | } --------------------------------------------------------------------------------