use std::char; use common::{is_name_start_char, is_name_char, is_whitespace_str}; use reader::lexer::Token; use super::{Result, PullParser, State}; impl PullParser { pub fn inside_reference(&mut self, t: Token, prev_st: State) -> Option { match t { Token::Character(c) if !self.data.ref_data.is_empty() && is_name_char(c) || self.data.ref_data.is_empty() && (is_name_start_char(c) || c == '#') => { self.data.ref_data.push(c); None } Token::ReferenceEnd => { // TODO: check for unicode correctness let name = self.data.take_ref_data(); let name_len = name.len(); // compute once let c = match &name[..] { "lt" => Ok('<'.to_string()), "gt" => Ok('>'.to_string()), "amp" => Ok('&'.to_string()), "apos" => Ok('\''.to_string()), "quot" => Ok('"'.to_string()), "" => Err(self_error!(self; "Encountered empty entity")), _ if name_len > 2 && name.starts_with("#x") => { let num_str = &name[2..name_len]; if num_str == "0" { Err(self_error!(self; "Null character entity is not allowed")) } else { if self.config.replace_unknown_entity_references { match u32::from_str_radix(num_str, 16).ok().map(|i| char::from_u32(i).unwrap_or('\u{fffd}')) { Some(c) => Ok(c.to_string()), None => Err(self_error!(self; "Invalid hexadecimal character number in an entity: {}", name)) } } else { match u32::from_str_radix(num_str, 16).ok().and_then(char::from_u32) { Some(c) => Ok(c.to_string()), None => Err(self_error!(self; "Invalid hexadecimal character number in an entity: {}", name)) } } } } _ if name_len > 1 && name.starts_with('#') => { let num_str = &name[1..name_len]; if num_str == "0" { Err(self_error!(self; "Null character entity is not allowed")) } else { if self.config.replace_unknown_entity_references { match u32::from_str_radix(num_str, 10).ok().map(|i| char::from_u32(i).unwrap_or('\u{fffd}')) { Some(c) => Ok(c.to_string()), None => Err(self_error!(self; "Invalid decimal character number in an entity: {}", name)) } } else { match u32::from_str_radix(num_str, 10).ok().and_then(char::from_u32) { Some(c) => Ok(c.to_string()), None => Err(self_error!(self; "Invalid decimal character number in an entity: {}", name)) } } } }, _ => { if let Some(v) = self.config.extra_entities.get(&name) { Ok(v.clone()) } else { Err(self_error!(self; "Unexpected entity: {}", name)) } } }; match c { Ok(c) => { self.buf.push_str(&c); if prev_st == State::OutsideTag && !is_whitespace_str(&c) { self.inside_whitespace = false; } self.into_state_continue(prev_st) } Err(e) => Some(e) } } _ => Some(self_error!(self; "Unexpected token inside an entity: {}", t)) } } }