diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/emitter.rs | 493 | ||||
| -rw-r--r-- | src/entities.rs | 15633 | ||||
| -rw-r--r-- | src/error.rs | 87 | ||||
| -rw-r--r-- | src/lib.rs | 2112 | ||||
| -rw-r--r-- | src/machine.rs | 164 | ||||
| -rw-r--r-- | src/reader.rs | 114 | 
6 files changed, 18603 insertions, 0 deletions
diff --git a/src/emitter.rs b/src/emitter.rs new file mode 100644 index 0000000..5bf1e0a --- /dev/null +++ b/src/emitter.rs @@ -0,0 +1,493 @@ +use std::collections::BTreeMap; +use std::collections::BTreeSet; +use std::collections::VecDeque; +use std::mem; + +use crate::Error; + +/// An emitter is an object providing methods to the tokenizer to produce tokens. +/// +/// Domain-specific applications of the HTML tokenizer can manually implement this trait to +/// customize per-token allocations, or avoid them altogether. +/// +/// An emitter is assumed to have these internal states: +/// +/// * _last start tag_: The most recently emitted start tag's name +/// * _current token_: Can be a tag, doctype or comment token. There's only one current token. +/// * _current attribute_: The currently processed HTML attribute, consisting of two strings for name and value. +/// +/// The following methods are describing what kind of behavior the WHATWG spec expects, but that +/// doesn't mean you need to follow it. For example: +/// +/// * If your usage of the tokenizer will ignore all errors, none of the error handling and +///   validation requirements apply to you. You can implement `emit_error` as noop and omit all +///   checks that would emit errors. +/// +/// * If you don't care about attributes at all, you can make all related methods a noop. +/// +/// The state machine needs to have a functional implementation of +/// `current_is_appropriate_end_tag_token` to do correct transitions, however. +pub trait Emitter { +    /// The token type emitted by this emitter. This controls what type of values the [`crate::Tokenizer`] +    /// yields when used as an iterator. +    type Token; + +    /// Set the name of the _last start tag_. +    /// +    /// This is primarily for testing purposes. This is *not* supposed to override the tag name of +    /// the current tag. +    fn set_last_start_tag(&mut self, last_start_tag: Option<&str>); + +    /// The state machine has reached the end of the file. It will soon call `pop_token` for the +    /// last time. +    fn emit_eof(&mut self); + +    /// A (probably recoverable) parsing error has occured. +    fn emit_error(&mut self, error: Error); + +    /// After every state change, the tokenizer calls this method to retrieve a new token that can +    /// be returned via the tokenizer's iterator interface. +    fn pop_token(&mut self) -> Option<Self::Token>; + +    /// Emit a bunch of plain characters as character tokens. +    fn emit_string(&mut self, c: &str); + +    /// Set the _current token_ to a start tag. +    fn init_start_tag(&mut self); + +    /// Set the _current token_ to an end tag. +    fn init_end_tag(&mut self); + +    /// Set the _current token_ to a comment. +    fn init_comment(&mut self); + +    /// Emit the _current token_, assuming it is a tag. +    /// +    /// Also get the current attribute and append it to the to-be-emitted tag. See docstring for +    /// [`Emitter::init_attribute`] for how duplicates should be handled. +    /// +    /// If a start tag is emitted, update the _last start tag_. +    /// +    /// If the current token is not a start/end tag, this method may panic. +    fn emit_current_tag(&mut self); + +    /// Emit the _current token_, assuming it is a comment. +    /// +    /// If the current token is not a comment, this method may panic. +    fn emit_current_comment(&mut self); + +    /// Emit the _current token_, assuming it is a doctype. +    /// +    /// If the current token is not a doctype, this method may panic. +    fn emit_current_doctype(&mut self); + +    /// Assuming the _current token_ is a start tag, set the self-closing flag. +    /// +    /// If the current token is not a start or end tag, this method may panic. +    /// +    /// If the current token is an end tag, the emitter should emit the +    /// [`crate::Error::EndTagWithTrailingSolidus`] error. +    fn set_self_closing(&mut self); + +    /// Assuming the _current token_ is a doctype, set its "force quirks" flag to true. +    /// +    /// If the current token is not a doctype, this method pay panic. +    fn set_force_quirks(&mut self); + +    /// Assuming the _current token_ is a start/end tag, append a string to the current tag's name. +    /// +    /// If the current token is not a start or end tag, this method may panic. +    fn push_tag_name(&mut self, s: &str); + +    /// Assuming the _current token_ is a comment, append a string to the comment's contents. +    /// +    /// If the current token is not a comment, this method may panic. +    fn push_comment(&mut self, s: &str); + +    /// Assuming the _current token_ is a doctype, append a string to the doctype's name. +    /// +    /// If the current token is not a doctype, this method may panic. +    fn push_doctype_name(&mut self, s: &str); + +    /// Set the _current token_ to a new doctype token: +    /// +    /// * the name should be empty +    /// * the "public identifier" should be null (different from empty) +    /// * the "system identifier" should be null (different from empty) +    /// * the "force quirks" flag should be `false` +    fn init_doctype(&mut self); + +    /// Set the _current attribute_ to a new one, starting with empty name and value strings. +    /// +    /// The old attribute, if any, should be put on the _current token_. If an attribute with that +    /// name already exists, WHATWG says the new one should be ignored and a +    /// [`crate::Error::DuplicateAttribute`] error should be emitted. +    /// +    /// If the current token is an end tag token, a [`crate::Error::EndTagWithAttributes`] error should be +    /// emitted. +    /// +    /// If the current token is no tag at all, this method may panic. +    fn init_attribute(&mut self); + +    /// Append a string to the current attribute's name. +    /// +    /// If there is no current attribute, this method may panic. +    fn push_attribute_name(&mut self, s: &str); + +    /// Append a string to the current attribute's value. +    /// +    /// If there is no current attribute, this method may panic. +    fn push_attribute_value(&mut self, s: &str); + +    /// Assuming the _current token_ is a doctype, set its "public identifier" to the given string. +    /// +    /// If the current token is not a doctype, this method may panic. +    fn set_doctype_public_identifier(&mut self, value: &str); + +    /// Assuming the _current token_ is a doctype, set its "system identifier" to the given string. +    /// +    /// If the current token is not a doctype, this method may panic. +    fn set_doctype_system_identifier(&mut self, value: &str); + +    /// Assuming the _current token_ is a doctype, append a string to its "public identifier" to the given string. +    /// +    /// If the current token is not a doctype, this method may panic. +    fn push_doctype_public_identifier(&mut self, s: &str); + +    /// Assuming the _current token_ is a doctype, append a string to its "system identifier" to the given string. +    /// +    /// If the current token is not a doctype, this method may panic. +    fn push_doctype_system_identifier(&mut self, s: &str); + +    /// Return true if all of these hold. Return false otherwise. +    /// +    /// * the _current token_ is an end tag +    /// * the _last start tag_ exists +    /// * the current end tag token's name equals to the last start tag's name. +    /// +    /// See also [WHATWG's definition of "appropriate end tag +    /// token"](https://html.spec.whatwg.org/#appropriate-end-tag-token). +    fn current_is_appropriate_end_tag_token(&mut self) -> bool; +} + +/// The default implementation of [`crate::Emitter`], used to produce ("emit") tokens. +pub struct DefaultEmitter { +    current_characters: String, +    current_token: Option<Token>, +    last_start_tag: String, +    current_attribute: Option<(String, String)>, +    seen_attributes: BTreeSet<String>, +    emitted_tokens: VecDeque<Token>, +} + +impl Default for DefaultEmitter { +    fn default() -> Self { +        DefaultEmitter { +            current_characters: String::new(), +            current_token: None, +            last_start_tag: String::new(), +            current_attribute: None, +            seen_attributes: BTreeSet::new(), +            emitted_tokens: VecDeque::new(), +        } +    } +} + +impl DefaultEmitter { +    fn emit_token(&mut self, token: Token) { +        self.flush_current_characters(); +        self.emitted_tokens.push_front(token); +    } + +    fn flush_current_attribute(&mut self) { +        if let Some((k, v)) = self.current_attribute.take() { +            match self.current_token { +                Some(Token::StartTag(ref mut tag)) => { +                    let mut error = None; +                    tag.attributes +                        .entry(k) +                        .and_modify(|_| { +                            error = Some(Error::DuplicateAttribute); +                        }) +                        .or_insert(v); + +                    if let Some(e) = error { +                        self.emit_error(e); +                    } +                } +                Some(Token::EndTag(_)) => { +                    if !self.seen_attributes.insert(k) { +                        self.emit_error(Error::DuplicateAttribute); +                    } +                } +                _ => { +                    debug_assert!(false); +                } +            } +        } +    } + +    fn flush_current_characters(&mut self) { +        if self.current_characters.is_empty() { +            return; +        } + +        let s = mem::take(&mut self.current_characters); +        self.emit_token(Token::String(s)); +    } +} + +impl Emitter for DefaultEmitter { +    type Token = Token; + +    fn set_last_start_tag(&mut self, last_start_tag: Option<&str>) { +        self.last_start_tag.clear(); +        self.last_start_tag +            .push_str(last_start_tag.unwrap_or_default()); +    } + +    fn emit_eof(&mut self) { +        self.flush_current_characters(); +    } + +    fn emit_error(&mut self, error: Error) { +        // bypass character flushing in self.emit_token: we don't need the error location to be +        // that exact +        self.emitted_tokens.push_front(Token::Error(error)); +    } + +    fn pop_token(&mut self) -> Option<Self::Token> { +        self.emitted_tokens.pop_back() +    } + +    fn emit_string(&mut self, s: &str) { +        self.current_characters.push_str(s); +    } + +    fn init_start_tag(&mut self) { +        self.current_token = Some(Token::StartTag(Default::default())); +    } +    fn init_end_tag(&mut self) { +        self.current_token = Some(Token::EndTag(Default::default())); +        self.seen_attributes.clear(); +    } + +    fn init_comment(&mut self) { +        self.current_token = Some(Token::Comment(String::new())); +    } +    fn emit_current_tag(&mut self) { +        self.flush_current_attribute(); +        let mut token = self.current_token.take().unwrap(); +        match token { +            Token::EndTag(_) => { +                if !self.seen_attributes.is_empty() { +                    self.emit_error(Error::EndTagWithAttributes); +                } +                self.seen_attributes.clear(); +            } +            Token::StartTag(ref mut _tag) => { +                self.set_last_start_tag(Some(&_tag.name)); +            } +            _ => debug_assert!(false), +        } +        self.emit_token(token); +    } +    fn emit_current_comment(&mut self) { +        let comment = self.current_token.take().unwrap(); +        debug_assert!(matches!(comment, Token::Comment(_))); +        self.emit_token(comment); +    } + +    fn emit_current_doctype(&mut self) { +        let doctype = self.current_token.take().unwrap(); +        debug_assert!(matches!(doctype, Token::Doctype(_))); +        self.emit_token(doctype); +    } + +    fn set_self_closing(&mut self) { +        let tag = self.current_token.as_mut().unwrap(); +        match tag { +            Token::StartTag(StartTag { +                ref mut self_closing, +                .. +            }) => { +                *self_closing = true; +            } +            Token::EndTag(_) => { +                self.emit_error(Error::EndTagWithTrailingSolidus); +            } +            _ => { +                debug_assert!(false); +            } +        } +    } +    fn set_force_quirks(&mut self) { +        match self.current_token { +            Some(Token::Doctype(ref mut doctype)) => doctype.force_quirks = true, +            _ => debug_assert!(false), +        } +    } +    fn push_tag_name(&mut self, s: &str) { +        match self.current_token { +            Some(Token::StartTag(StartTag { ref mut name, .. })) => { +                name.push_str(s); +            } +            Some(Token::EndTag(EndTag { ref mut name, .. })) => { +                name.push_str(s); +            } +            _ => debug_assert!(false), +        } +    } + +    fn push_comment(&mut self, s: &str) { +        match self.current_token { +            Some(Token::Comment(ref mut data)) => data.push_str(s), +            _ => debug_assert!(false), +        } +    } + +    fn push_doctype_name(&mut self, s: &str) { +        match self.current_token { +            Some(Token::Doctype(ref mut doctype)) => doctype.name.push_str(s), +            _ => debug_assert!(false), +        } +    } +    fn init_doctype(&mut self) { +        self.current_token = Some(Token::Doctype(Doctype { +            name: String::new(), +            force_quirks: false, +            public_identifier: None, +            system_identifier: None, +        })); +    } + +    fn init_attribute(&mut self) { +        self.flush_current_attribute(); +        self.current_attribute = Some((String::new(), String::new())); +    } +    fn push_attribute_name(&mut self, s: &str) { +        self.current_attribute.as_mut().unwrap().0.push_str(s); +    } +    fn push_attribute_value(&mut self, s: &str) { +        self.current_attribute.as_mut().unwrap().1.push_str(s); +    } +    fn set_doctype_public_identifier(&mut self, value: &str) { +        if let Some(Token::Doctype(Doctype { +            ref mut public_identifier, +            .. +        })) = self.current_token +        { +            *public_identifier = Some(value.to_owned()); +        } else { +            debug_assert!(false); +        } +    } +    fn set_doctype_system_identifier(&mut self, value: &str) { +        if let Some(Token::Doctype(Doctype { +            ref mut system_identifier, +            .. +        })) = self.current_token +        { +            *system_identifier = Some(value.to_owned()); +        } else { +            debug_assert!(false); +        } +    } +    fn push_doctype_public_identifier(&mut self, s: &str) { +        if let Some(Token::Doctype(Doctype { +            public_identifier: Some(ref mut id), +            .. +        })) = self.current_token +        { +            id.push_str(s); +        } else { +            debug_assert!(false); +        } +    } +    fn push_doctype_system_identifier(&mut self, s: &str) { +        if let Some(Token::Doctype(Doctype { +            system_identifier: Some(ref mut id), +            .. +        })) = self.current_token +        { +            id.push_str(s); +        } else { +            debug_assert!(false); +        } +    } + +    fn current_is_appropriate_end_tag_token(&mut self) -> bool { +        match self.current_token { +            Some(Token::EndTag(ref tag)) => { +                !self.last_start_tag.is_empty() && self.last_start_tag == tag.name +            } +            _ => false, +        } +    } +} + +/// A HTML end/close tag, such as `<p>` or `<a>`. +#[derive(Debug, Default, Eq, PartialEq)] +pub struct StartTag { +    /// Whether this tag is self-closing. If it is self-closing, no following [`EndTag`] should be +    /// expected. +    pub self_closing: bool, + +    /// The start tag's name, such as `"p"` or `"a"`. +    pub name: String, + +    /// A mapping for any HTML attributes this start tag may have. +    /// +    /// Duplicate attributes are ignored after the first one as per WHATWG spec. Implement your own +    /// [`Emitter`] to tweak this behavior. +    pub attributes: BTreeMap<String, String>, +} + +/// A HTML end/close tag, such as `</p>` or `</a>`. +#[derive(Debug, Default, Eq, PartialEq)] +pub struct EndTag { +    /// The ending tag's name, such as `"p"` or `"a"`. +    pub name: String, +} + +/// A doctype. Some examples: +/// +/// * `<!DOCTYPE {name}>` +/// * `<!DOCTYPE {name} PUBLIC '{public_identifier}'>` +/// * `<!DOCTYPE {name} SYSTEM '{system_identifier}'>` +/// * `<!DOCTYPE {name} PUBLIC '{public_identifier}' '{system_identifier}'>` +#[derive(Debug, Eq, PartialEq)] +pub struct Doctype { +    /// The ["force quirks"](https://html.spec.whatwg.org/#force-quirks-flag) flag. +    pub force_quirks: bool, + +    /// The doctype's name. For HTML documents this is "html". +    pub name: String, + +    /// The doctype's public identifier. +    pub public_identifier: Option<String>, + +    /// The doctype's system identifier. +    pub system_identifier: Option<String>, +} + +/// The token type used by default. You can define your own token type by implementing the +/// [`crate::Emitter`] trait and using [`crate::Tokenizer::new_with_emitter`]. +#[derive(Debug, Eq, PartialEq)] +pub enum Token { +    /// A HTML start tag. +    StartTag(StartTag), +    /// A HTML end tag. +    EndTag(EndTag), +    /// A literal string. +    String(String), +    /// A HTML comment. +    Comment(String), +    /// A HTML doctype declaration. +    Doctype(Doctype), +    /// A HTML parsing error. +    /// +    /// Can be skipped over, the tokenizer is supposed to recover from the error and continues with +    /// more tokens afterward. +    Error(Error), +} diff --git a/src/entities.rs b/src/entities.rs new file mode 100644 index 0000000..1ab3ffb --- /dev/null +++ b/src/entities.rs @@ -0,0 +1,15633 @@ +// @generated +// this file is autogenerated by +// curl https://html.spec.whatwg.org/entities.json | python generate_entities.py + +pub struct CharRef { +    /// Name as it appears escaped in HTML +    pub name: &'static str, +    /// Unescaped character codepoints +    pub characters: &'static str, +} + +pub fn try_read_character_reference( +    first_char: char, +    mut try_read: impl FnMut(&str) -> bool, +) -> Option<CharRef> { +    if first_char == 'C' && try_read("ounterClockwiseContourIntegral;") { +        return Some(CharRef { +            name: "ounterClockwiseContourIntegral;", +            characters: "\u{2233}", +        }); +    } + +    if first_char == 'C' && try_read("lockwiseContourIntegral;") { +        return Some(CharRef { +            name: "lockwiseContourIntegral;", +            characters: "\u{2232}", +        }); +    } + +    if first_char == 'D' && try_read("oubleLongLeftRightArrow;") { +        return Some(CharRef { +            name: "oubleLongLeftRightArrow;", +            characters: "\u{27fa}", +        }); +    } + +    if first_char == 'N' && try_read("otNestedGreaterGreater;") { +        return Some(CharRef { +            name: "otNestedGreaterGreater;", +            characters: "\u{2aa2}\u{338}", +        }); +    } + +    if first_char == 'D' && try_read("iacriticalDoubleAcute;") { +        return Some(CharRef { +            name: "iacriticalDoubleAcute;", +            characters: "\u{2dd}", +        }); +    } + +    if first_char == 'N' && try_read("otSquareSupersetEqual;") { +        return Some(CharRef { +            name: "otSquareSupersetEqual;", +            characters: "\u{22e3}", +        }); +    } + +    if first_char == 'C' && try_read("loseCurlyDoubleQuote;") { +        return Some(CharRef { +            name: "loseCurlyDoubleQuote;", +            characters: "\u{201d}", +        }); +    } + +    if first_char == 'D' && try_read("oubleContourIntegral;") { +        return Some(CharRef { +            name: "oubleContourIntegral;", +            characters: "\u{222f}", +        }); +    } + +    if first_char == 'F' && try_read("illedVerySmallSquare;") { +        return Some(CharRef { +            name: "illedVerySmallSquare;", +            characters: "\u{25aa}", +        }); +    } + +    if first_char == 'N' && try_read("egativeVeryThinSpace;") { +        return Some(CharRef { +            name: "egativeVeryThinSpace;", +            characters: "\u{200b}", +        }); +    } + +    if first_char == 'N' && try_read("otPrecedesSlantEqual;") { +        return Some(CharRef { +            name: "otPrecedesSlantEqual;", +            characters: "\u{22e0}", +        }); +    } + +    if first_char == 'N' && try_read("otRightTriangleEqual;") { +        return Some(CharRef { +            name: "otRightTriangleEqual;", +            characters: "\u{22ed}", +        }); +    } + +    if first_char == 'N' && try_read("otSucceedsSlantEqual;") { +        return Some(CharRef { +            name: "otSucceedsSlantEqual;", +            characters: "\u{22e1}", +        }); +    } + +    if first_char == 'C' && try_read("apitalDifferentialD;") { +        return Some(CharRef { +            name: "apitalDifferentialD;", +            characters: "\u{2145}", +        }); +    } + +    if first_char == 'D' && try_read("oubleLeftRightArrow;") { +        return Some(CharRef { +            name: "oubleLeftRightArrow;", +            characters: "\u{21d4}", +        }); +    } + +    if first_char == 'D' && try_read("oubleLongRightArrow;") { +        return Some(CharRef { +            name: "oubleLongRightArrow;", +            characters: "\u{27f9}", +        }); +    } + +    if first_char == 'E' && try_read("mptyVerySmallSquare;") { +        return Some(CharRef { +            name: "mptyVerySmallSquare;", +            characters: "\u{25ab}", +        }); +    } + +    if first_char == 'N' && try_read("estedGreaterGreater;") { +        return Some(CharRef { +            name: "estedGreaterGreater;", +            characters: "\u{226b}", +        }); +    } + +    if first_char == 'N' && try_read("otDoubleVerticalBar;") { +        return Some(CharRef { +            name: "otDoubleVerticalBar;", +            characters: "\u{2226}", +        }); +    } + +    if first_char == 'N' && try_read("otGreaterSlantEqual;") { +        return Some(CharRef { +            name: "otGreaterSlantEqual;", +            characters: "\u{2a7e}\u{338}", +        }); +    } + +    if first_char == 'N' && try_read("otLeftTriangleEqual;") { +        return Some(CharRef { +            name: "otLeftTriangleEqual;", +            characters: "\u{22ec}", +        }); +    } + +    if first_char == 'N' && try_read("otSquareSubsetEqual;") { +        return Some(CharRef { +            name: "otSquareSubsetEqual;", +            characters: "\u{22e2}", +        }); +    } + +    if first_char == 'O' && try_read("penCurlyDoubleQuote;") { +        return Some(CharRef { +            name: "penCurlyDoubleQuote;", +            characters: "\u{201c}", +        }); +    } + +    if first_char == 'R' && try_read("everseUpEquilibrium;") { +        return Some(CharRef { +            name: "everseUpEquilibrium;", +            characters: "\u{296f}", +        }); +    } + +    if first_char == 'D' && try_read("oubleLongLeftArrow;") { +        return Some(CharRef { +            name: "oubleLongLeftArrow;", +            characters: "\u{27f8}", +        }); +    } + +    if first_char == 'D' && try_read("ownLeftRightVector;") { +        return Some(CharRef { +            name: "ownLeftRightVector;", +            characters: "\u{2950}", +        }); +    } + +    if first_char == 'L' && try_read("eftArrowRightArrow;") { +        return Some(CharRef { +            name: "eftArrowRightArrow;", +            characters: "\u{21c6}", +        }); +    } + +    if first_char == 'N' && try_read("egativeMediumSpace;") { +        return Some(CharRef { +            name: "egativeMediumSpace;", +            characters: "\u{200b}", +        }); +    } + +    if first_char == 'N' && try_read("otGreaterFullEqual;") { +        return Some(CharRef { +            name: "otGreaterFullEqual;", +            characters: "\u{2267}\u{338}", +        }); +    } + +    if first_char == 'N' && try_read("otRightTriangleBar;") { +        return Some(CharRef { +            name: "otRightTriangleBar;", +            characters: "\u{29d0}\u{338}", +        }); +    } + +    if first_char == 'R' && try_read("ightArrowLeftArrow;") { +        return Some(CharRef { +            name: "ightArrowLeftArrow;", +            characters: "\u{21c4}", +        }); +    } + +    if first_char == 'S' && try_read("quareSupersetEqual;") { +        return Some(CharRef { +            name: "quareSupersetEqual;", +            characters: "\u{2292}", +        }); +    } + +    if first_char == 'l' && try_read("eftrightsquigarrow;") { +        return Some(CharRef { +            name: "eftrightsquigarrow;", +            characters: "\u{21ad}", +        }); +    } + +    if first_char == 'D' && try_read("ownRightTeeVector;") { +        return Some(CharRef { +            name: "ownRightTeeVector;", +            characters: "\u{295f}", +        }); +    } + +    if first_char == 'D' && try_read("ownRightVectorBar;") { +        return Some(CharRef { +            name: "ownRightVectorBar;", +            characters: "\u{2957}", +        }); +    } + +    if first_char == 'L' && try_read("ongLeftRightArrow;") { +        return Some(CharRef { +            name: "ongLeftRightArrow;", +            characters: "\u{27f7}", +        }); +    } + +    if first_char == 'L' && try_read("ongleftrightarrow;") { +        return Some(CharRef { +            name: "ongleftrightarrow;", +            characters: "\u{27fa}", +        }); +    } + +    if first_char == 'N' && try_read("egativeThickSpace;") { +        return Some(CharRef { +            name: "egativeThickSpace;", +            characters: "\u{200b}", +        }); +    } + +    if first_char == 'N' && try_read("otLeftTriangleBar;") { +        return Some(CharRef { +            name: "otLeftTriangleBar;", +            characters: "\u{29cf}\u{338}", +        }); +    } + +    if first_char == 'P' && try_read("recedesSlantEqual;") { +        return Some(CharRef { +            name: "recedesSlantEqual;", +            characters: "\u{227c}", +        }); +    } + +    if first_char == 'R' && try_read("everseEquilibrium;") { +        return Some(CharRef { +            name: "everseEquilibrium;", +            characters: "\u{21cb}", +        }); +    } + +    if first_char == 'R' && try_read("ightDoubleBracket;") { +        return Some(CharRef { +            name: "ightDoubleBracket;", +            characters: "\u{27e7}", +        }); +    } + +    if first_char == 'R' && try_read("ightDownTeeVector;") { +        return Some(CharRef { +            name: "ightDownTeeVector;", +            characters: "\u{295d}", +        }); +    } + +    if first_char == 'R' && try_read("ightDownVectorBar;") { +        return Some(CharRef { +            name: "ightDownVectorBar;", +            characters: "\u{2955}", +        }); +    } + +    if first_char == 'R' && try_read("ightTriangleEqual;") { +        return Some(CharRef { +            name: "ightTriangleEqual;", +            characters: "\u{22b5}", +        }); +    } + +    if first_char == 'S' && try_read("quareIntersection;") { +        return Some(CharRef { +            name: "quareIntersection;", +            characters: "\u{2293}", +        }); +    } + +    if first_char == 'S' && try_read("ucceedsSlantEqual;") { +        return Some(CharRef { +            name: "ucceedsSlantEqual;", +            characters: "\u{227d}", +        }); +    } + +    if first_char == 'b' && try_read("lacktriangleright;") { +        return Some(CharRef { +            name: "lacktriangleright;", +            characters: "\u{25b8}", +        }); +    } + +    if first_char == 'l' && try_read("ongleftrightarrow;") { +        return Some(CharRef { +            name: "ongleftrightarrow;", +            characters: "\u{27f7}", +        }); +    } + +    if first_char == 'D' && try_read("oubleUpDownArrow;") { +        return Some(CharRef { +            name: "oubleUpDownArrow;", +            characters: "\u{21d5}", +        }); +    } + +    if first_char == 'D' && try_read("oubleVerticalBar;") { +        return Some(CharRef { +            name: "oubleVerticalBar;", +            characters: "\u{2225}", +        }); +    } + +    if first_char == 'D' && try_read("ownLeftTeeVector;") { +        return Some(CharRef { +            name: "ownLeftTeeVector;", +            characters: "\u{295e}", +        }); +    } + +    if first_char == 'D' && try_read("ownLeftVectorBar;") { +        return Some(CharRef { +            name: "ownLeftVectorBar;", +            characters: "\u{2956}", +        }); +    } + +    if first_char == 'F' && try_read("illedSmallSquare;") { +        return Some(CharRef { +            name: "illedSmallSquare;", +            characters: "\u{25fc}", +        }); +    } + +    if first_char == 'G' && try_read("reaterSlantEqual;") { +        return Some(CharRef { +            name: "reaterSlantEqual;", +            characters: "\u{2a7e}", +        }); +    } + +    if first_char == 'L' && try_read("eftDoubleBracket;") { +        return Some(CharRef { +            name: "eftDoubleBracket;", +            characters: "\u{27e6}", +        }); +    } + +    if first_char == 'L' && try_read("eftDownTeeVector;") { +        return Some(CharRef { +            name: "eftDownTeeVector;", +            characters: "\u{2961}", +        }); +    } + +    if first_char == 'L' && try_read("eftDownVectorBar;") { +        return Some(CharRef { +            name: "eftDownVectorBar;", +            characters: "\u{2959}", +        }); +    } + +    if first_char == 'L' && try_read("eftTriangleEqual;") { +        return Some(CharRef { +            name: "eftTriangleEqual;", +            characters: "\u{22b4}", +        }); +    } + +    if first_char == 'N' && try_read("egativeThinSpace;") { +        return Some(CharRef { +            name: "egativeThinSpace;", +            characters: "\u{200b}", +        }); +    } + +    if first_char == 'N' && try_read("otGreaterGreater;") { +        return Some(CharRef { +            name: "otGreaterGreater;", +            characters: "\u{226b}\u{338}", +        }); +    } + +    if first_char == 'N' && try_read("otLessSlantEqual;") { +        return Some(CharRef { +            name: "otLessSlantEqual;", +            characters: "\u{2a7d}\u{338}", +        }); +    } + +    if first_char == 'N' && try_read("otNestedLessLess;") { +        return Some(CharRef { +            name: "otNestedLessLess;", +            characters: "\u{2aa1}\u{338}", +        }); +    } + +    if first_char == 'N' && try_read("otReverseElement;") { +        return Some(CharRef { +            name: "otReverseElement;", +            characters: "\u{220c}", +        }); +    } + +    if first_char == 'N' && try_read("otSquareSuperset;") { +        return Some(CharRef { +            name: "otSquareSuperset;", +            characters: "\u{2290}\u{338}", +        }); +    } + +    if first_char == 'N' && try_read("otTildeFullEqual;") { +        return Some(CharRef { +            name: "otTildeFullEqual;", +            characters: "\u{2247}", +        }); +    } + +    if first_char == 'R' && try_read("ightAngleBracket;") { +        return Some(CharRef { +            name: "ightAngleBracket;", +            characters: "\u{27e9}", +        }); +    } + +    if first_char == 'R' && try_read("ightUpDownVector;") { +        return Some(CharRef { +            name: "ightUpDownVector;", +            characters: "\u{294f}", +        }); +    } + +    if first_char == 'S' && try_read("quareSubsetEqual;") { +        return Some(CharRef { +            name: "quareSubsetEqual;", +            characters: "\u{2291}", +        }); +    } + +    if first_char == 'V' && try_read("erticalSeparator;") { +        return Some(CharRef { +            name: "erticalSeparator;", +            characters: "\u{2758}", +        }); +    } + +    if first_char == 'b' && try_read("lacktriangledown;") { +        return Some(CharRef { +            name: "lacktriangledown;", +            characters: "\u{25be}", +        }); +    } + +    if first_char == 'b' && try_read("lacktriangleleft;") { +        return Some(CharRef { +            name: "lacktriangleleft;", +            characters: "\u{25c2}", +        }); +    } + +    if first_char == 'l' && try_read("eftrightharpoons;") { +        return Some(CharRef { +            name: "eftrightharpoons;", +            characters: "\u{21cb}", +        }); +    } + +    if first_char == 'r' && try_read("ightleftharpoons;") { +        return Some(CharRef { +            name: "ightleftharpoons;", +            characters: "\u{21cc}", +        }); +    } + +    if first_char == 't' && try_read("woheadrightarrow;") { +        return Some(CharRef { +            name: "woheadrightarrow;", +            characters: "\u{21a0}", +        }); +    } + +    if first_char == 'D' && try_read("iacriticalAcute;") { +        return Some(CharRef { +            name: "iacriticalAcute;", +            characters: "\u{b4}", +        }); +    } + +    if first_char == 'D' && try_read("iacriticalGrave;") { +        return Some(CharRef { +            name: "iacriticalGrave;", +            characters: "\u{60}", +        }); +    } + +    if first_char == 'D' && try_read("iacriticalTilde;") { +        return Some(CharRef { +            name: "iacriticalTilde;", +            characters: "\u{2dc}", +        }); +    } + +    if first_char == 'D' && try_read("oubleRightArrow;") { +        return Some(CharRef { +            name: "oubleRightArrow;", +            characters: "\u{21d2}", +        }); +    } + +    if first_char == 'D' && try_read("ownArrowUpArrow;") { +        return Some(CharRef { +            name: "ownArrowUpArrow;", +            characters: "\u{21f5}", +        }); +    } + +    if first_char == 'E' && try_read("mptySmallSquare;") { +        return Some(CharRef { +            name: "mptySmallSquare;", +            characters: "\u{25fb}", +        }); +    } + +    if first_char == 'G' && try_read("reaterEqualLess;") { +        return Some(CharRef { +            name: "reaterEqualLess;", +            characters: "\u{22db}", +        }); +    } + +    if first_char == 'G' && try_read("reaterFullEqual;") { +        return Some(CharRef { +            name: "reaterFullEqual;", +            characters: "\u{2267}", +        }); +    } + +    if first_char == 'L' && try_read("eftAngleBracket;") { +        return Some(CharRef { +            name: "eftAngleBracket;", +            characters: "\u{27e8}", +        }); +    } + +    if first_char == 'L' && try_read("eftUpDownVector;") { +        return Some(CharRef { +            name: "eftUpDownVector;", +            characters: "\u{2951}", +        }); +    } + +    if first_char == 'L' && try_read("essEqualGreater;") { +        return Some(CharRef { +            name: "essEqualGreater;", +            characters: "\u{22da}", +        }); +    } + +    if first_char == 'N' && try_read("onBreakingSpace;") { +        return Some(CharRef { +            name: "onBreakingSpace;", +            characters: "\u{a0}", +        }); +    } + +    if first_char == 'N' && try_read("otPrecedesEqual;") { +        return Some(CharRef { +            name: "otPrecedesEqual;", +            characters: "\u{2aaf}\u{338}", +        }); +    } + +    if first_char == 'N' && try_read("otRightTriangle;") { +        return Some(CharRef { +            name: "otRightTriangle;", +            characters: "\u{22eb}", +        }); +    } + +    if first_char == 'N' && try_read("otSucceedsEqual;") { +        return Some(CharRef { +            name: "otSucceedsEqual;", +            characters: "\u{2ab0}\u{338}", +        }); +    } + +    if first_char == 'N' && try_read("otSucceedsTilde;") { +        return Some(CharRef { +            name: "otSucceedsTilde;", +            characters: "\u{227f}\u{338}", +        }); +    } + +    if first_char == 'N' && try_read("otSupersetEqual;") { +        return Some(CharRef { +            name: "otSupersetEqual;", +            characters: "\u{2289}", +        }); +    } + +    if first_char == 'R' && try_read("ightTriangleBar;") { +        return Some(CharRef { +            name: "ightTriangleBar;", +            characters: "\u{29d0}", +        }); +    } + +    if first_char == 'R' && try_read("ightUpTeeVector;") { +        return Some(CharRef { +            name: "ightUpTeeVector;", +            characters: "\u{295c}", +        }); +    } + +    if first_char == 'R' && try_read("ightUpVectorBar;") { +        return Some(CharRef { +            name: "ightUpVectorBar;", +            characters: "\u{2954}", +        }); +    } + +    if first_char == 'U' && try_read("nderParenthesis;") { +        return Some(CharRef { +            name: "nderParenthesis;", +            characters: "\u{23dd}", +        }); +    } + +    if first_char == 'U' && try_read("pArrowDownArrow;") { +        return Some(CharRef { +            name: "pArrowDownArrow;", +            characters: "\u{21c5}", +        }); +    } + +    if first_char == 'c' && try_read("irclearrowright;") { +        return Some(CharRef { +            name: "irclearrowright;", +            characters: "\u{21bb}", +        }); +    } + +    if first_char == 'd' && try_read("ownharpoonright;") { +        return Some(CharRef { +            name: "ownharpoonright;", +            characters: "\u{21c2}", +        }); +    } + +    if first_char == 'n' && try_read("trianglerighteq;") { +        return Some(CharRef { +            name: "trianglerighteq;", +            characters: "\u{22ed}", +        }); +    } + +    if first_char == 'r' && try_read("ightharpoondown;") { +        return Some(CharRef { +            name: "ightharpoondown;", +            characters: "\u{21c1}", +        }); +    } + +    if first_char == 'r' && try_read("ightrightarrows;") { +        return Some(CharRef { +            name: "ightrightarrows;", +            characters: "\u{21c9}", +        }); +    } + +    if first_char == 't' && try_read("woheadleftarrow;") { +        return Some(CharRef { +            name: "woheadleftarrow;", +            characters: "\u{219e}", +        }); +    } + +    if first_char == 'v' && try_read("artriangleright;") { +        return Some(CharRef { +            name: "artriangleright;", +            characters: "\u{22b3}", +        }); +    } + +    if first_char == 'C' && try_read("loseCurlyQuote;") { +        return Some(CharRef { +            name: "loseCurlyQuote;", +            characters: "\u{2019}", +        }); +    } + +    if first_char == 'C' && try_read("ontourIntegral;") { +        return Some(CharRef { +            name: "ontourIntegral;", +            characters: "\u{222e}", +        }); +    } + +    if first_char == 'D' && try_read("oubleDownArrow;") { +        return Some(CharRef { +            name: "oubleDownArrow;", +            characters: "\u{21d3}", +        }); +    } + +    if first_char == 'D' && try_read("oubleLeftArrow;") { +        return Some(CharRef { +            name: "oubleLeftArrow;", +            characters: "\u{21d0}", +        }); +    } + +    if first_char == 'D' && try_read("ownRightVector;") { +        return Some(CharRef { +            name: "ownRightVector;", +            characters: "\u{21c1}", +        }); +    } + +    if first_char == 'L' && try_read("eftRightVector;") { +        return Some(CharRef { +            name: "eftRightVector;", +            characters: "\u{294e}", +        }); +    } + +    if first_char == 'L' && try_read("eftTriangleBar;") { +        return Some(CharRef { +            name: "eftTriangleBar;", +            characters: "\u{29cf}", +        }); +    } + +    if first_char == 'L' && try_read("eftUpTeeVector;") { +        return Some(CharRef { +            name: "eftUpTeeVector;", +            characters: "\u{2960}", +        }); +    } + +    if first_char == 'L' && try_read("eftUpVectorBar;") { +        return Some(CharRef { +            name: "eftUpVectorBar;", +            characters: "\u{2958}", +        }); +    } + +    if first_char == 'L' && try_read("owerRightArrow;") { +        return Some(CharRef { +            name: "owerRightArrow;", +            characters: "\u{2198}", +        }); +    } + +    if first_char == 'N' && try_read("otGreaterEqual;") { +        return Some(CharRef { +            name: "otGreaterEqual;", +            characters: "\u{2271}", +        }); +    } + +    if first_char == 'N' && try_read("otGreaterTilde;") { +        return Some(CharRef { +            name: "otGreaterTilde;", +            characters: "\u{2275}", +        }); +    } + +    if first_char == 'N' && try_read("otHumpDownHump;") { +        return Some(CharRef { +            name: "otHumpDownHump;", +            characters: "\u{224e}\u{338}", +        }); +    } + +    if first_char == 'N' && try_read("otLeftTriangle;") { +        return Some(CharRef { +            name: "otLeftTriangle;", +            characters: "\u{22ea}", +        }); +    } + +    if first_char == 'N' && try_read("otSquareSubset;") { +        return Some(CharRef { +            name: "otSquareSubset;", +            characters: "\u{228f}\u{338}", +        }); +    } + +    if first_char == 'O' && try_read("verParenthesis;") { +        return Some(CharRef { +            name: "verParenthesis;", +            characters: "\u{23dc}", +        }); +    } + +    if first_char == 'R' && try_read("ightDownVector;") { +        return Some(CharRef { +            name: "ightDownVector;", +            characters: "\u{21c2}", +        }); +    } + +    if first_char == 'S' && try_read("hortRightArrow;") { +        return Some(CharRef { +            name: "hortRightArrow;", +            characters: "\u{2192}", +        }); +    } + +    if first_char == 'U' && try_read("pperRightArrow;") { +        return Some(CharRef { +            name: "pperRightArrow;", +            characters: "\u{2197}", +        }); +    } + +    if first_char == 'b' && try_read("igtriangledown;") { +        return Some(CharRef { +            name: "igtriangledown;", +            characters: "\u{25bd}", +        }); +    } + +    if first_char == 'c' && try_read("irclearrowleft;") { +        return Some(CharRef { +            name: "irclearrowleft;", +            characters: "\u{21ba}", +        }); +    } + +    if first_char == 'c' && try_read("urvearrowright;") { +        return Some(CharRef { +            name: "urvearrowright;", +            characters: "\u{21b7}", +        }); +    } + +    if first_char == 'd' && try_read("ownharpoonleft;") { +        return Some(CharRef { +            name: "ownharpoonleft;", +            characters: "\u{21c3}", +        }); +    } + +    if first_char == 'l' && try_read("eftharpoondown;") { +        return Some(CharRef { +            name: "eftharpoondown;", +            characters: "\u{21bd}", +        }); +    } + +    if first_char == 'l' && try_read("eftrightarrows;") { +        return Some(CharRef { +            name: "eftrightarrows;", +            characters: "\u{21c6}", +        }); +    } + +    if first_char == 'n' && try_read("Leftrightarrow;") { +        return Some(CharRef { +            name: "Leftrightarrow;", +            characters: "\u{21ce}", +        }); +    } + +    if first_char == 'n' && try_read("leftrightarrow;") { +        return Some(CharRef { +            name: "leftrightarrow;", +            characters: "\u{21ae}", +        }); +    } + +    if first_char == 'n' && try_read("trianglelefteq;") { +        return Some(CharRef { +            name: "trianglelefteq;", +            characters: "\u{22ec}", +        }); +    } + +    if first_char == 'r' && try_read("ightleftarrows;") { +        return Some(CharRef { +            name: "ightleftarrows;", +            characters: "\u{21c4}", +        }); +    } + +    if first_char == 'r' && try_read("ightsquigarrow;") { +        return Some(CharRef { +            name: "ightsquigarrow;", +            characters: "\u{219d}", +        }); +    } + +    if first_char == 'r' && try_read("ightthreetimes;") { +        return Some(CharRef { +            name: "ightthreetimes;", +            characters: "\u{22cc}", +        }); +    } + +    if first_char == 's' && try_read("traightepsilon;") { +        return Some(CharRef { +            name: "traightepsilon;", +            characters: "\u{3f5}", +        }); +    } + +    if first_char == 't' && try_read("rianglerighteq;") { +        return Some(CharRef { +            name: "rianglerighteq;", +            characters: "\u{22b5}", +        }); +    } + +    if first_char == 'v' && try_read("artriangleleft;") { +        return Some(CharRef { +            name: "artriangleleft;", +            characters: "\u{22b2}", +        }); +    } + +    if first_char == 'D' && try_read("iacriticalDot;") { +        return Some(CharRef { +            name: "iacriticalDot;", +            characters: "\u{2d9}", +        }); +    } + +    if first_char == 'D' && try_read("oubleRightTee;") { +        return Some(CharRef { +            name: "oubleRightTee;", +            characters: "\u{22a8}", +        }); +    } + +    if first_char == 'D' && try_read("ownLeftVector;") { +        return Some(CharRef { +            name: "ownLeftVector;", +            characters: "\u{21bd}", +        }); +    } + +    if first_char == 'G' && try_read("reaterGreater;") { +        return Some(CharRef { +            name: "reaterGreater;", +            characters: "\u{2aa2}", +        }); +    } + +    if first_char == 'H' && try_read("orizontalLine;") { +        return Some(CharRef { +            name: "orizontalLine;", +            characters: "\u{2500}", +        }); +    } + +    if first_char == 'I' && try_read("nvisibleComma;") { +        return Some(CharRef { +            name: "nvisibleComma;", +            characters: "\u{2063}", +        }); +    } + +    if first_char == 'I' && try_read("nvisibleTimes;") { +        return Some(CharRef { +            name: "nvisibleTimes;", +            characters: "\u{2062}", +        }); +    } + +    if first_char == 'L' && try_read("eftDownVector;") { +        return Some(CharRef { +            name: "eftDownVector;", +            characters: "\u{21c3}", +        }); +    } + +    if first_char == 'L' && try_read("eftRightArrow;") { +        return Some(CharRef { +            name: "eftRightArrow;", +            characters: "\u{2194}", +        }); +    } + +    if first_char == 'L' && try_read("eftrightarrow;") { +        return Some(CharRef { +            name: "eftrightarrow;", +            characters: "\u{21d4}", +        }); +    } + +    if first_char == 'L' && try_read("essSlantEqual;") { +        return Some(CharRef { +            name: "essSlantEqual;", +            characters: "\u{2a7d}", +        }); +    } + +    if first_char == 'L' && try_read("ongRightArrow;") { +        return Some(CharRef { +            name: "ongRightArrow;", +            characters: "\u{27f6}", +        }); +    } + +    if first_char == 'L' && try_read("ongrightarrow;") { +        return Some(CharRef { +            name: "ongrightarrow;", +            characters: "\u{27f9}", +        }); +    } + +    if first_char == 'L' && try_read("owerLeftArrow;") { +        return Some(CharRef { +            name: "owerLeftArrow;", +            characters: "\u{2199}", +        }); +    } + +    if first_char == 'N' && try_read("estedLessLess;") { +        return Some(CharRef { +            name: "estedLessLess;", +            characters: "\u{226a}", +        }); +    } + +    if first_char == 'N' && try_read("otGreaterLess;") { +        return Some(CharRef { +            name: "otGreaterLess;", +            characters: "\u{2279}", +        }); +    } + +    if first_char == 'N' && try_read("otLessGreater;") { +        return Some(CharRef { +            name: "otLessGreater;", +            characters: "\u{2278}", +        }); +    } + +    if first_char == 'N' && try_read("otSubsetEqual;") { +        return Some(CharRef { +            name: "otSubsetEqual;", +            characters: "\u{2288}", +        }); +    } + +    if first_char == 'N' && try_read("otVerticalBar;") { +        return Some(CharRef { +            name: "otVerticalBar;", +            characters: "\u{2224}", +        }); +    } + +    if first_char == 'O' && try_read("penCurlyQuote;") { +        return Some(CharRef { +            name: "penCurlyQuote;", +            characters: "\u{2018}", +        }); +    } + +    if first_char == 'R' && try_read("everseElement;") { +        return Some(CharRef { +            name: "everseElement;", +            characters: "\u{220b}", +        }); +    } + +    if first_char == 'R' && try_read("ightTeeVector;") { +        return Some(CharRef { +            name: "ightTeeVector;", +            characters: "\u{295b}", +        }); +    } + +    if first_char == 'R' && try_read("ightVectorBar;") { +        return Some(CharRef { +            name: "ightVectorBar;", +            characters: "\u{2953}", +        }); +    } + +    if first_char == 'S' && try_read("hortDownArrow;") { +        return Some(CharRef { +            name: "hortDownArrow;", +            characters: "\u{2193}", +        }); +    } + +    if first_char == 'S' && try_read("hortLeftArrow;") { +        return Some(CharRef { +            name: "hortLeftArrow;", +            characters: "\u{2190}", +        }); +    } + +    if first_char == 'S' && try_read("quareSuperset;") { +        return Some(CharRef { +            name: "quareSuperset;", +            characters: "\u{2290}", +        }); +    } + +    if first_char == 'T' && try_read("ildeFullEqual;") { +        return Some(CharRef { +            name: "ildeFullEqual;", +            characters: "\u{2245}", +        }); +    } + +    if first_char == 'U' && try_read("pperLeftArrow;") { +        return Some(CharRef { +            name: "pperLeftArrow;", +            characters: "\u{2196}", +        }); +    } + +    if first_char == 'Z' && try_read("eroWidthSpace;") { +        return Some(CharRef { +            name: "eroWidthSpace;", +            characters: "\u{200b}", +        }); +    } + +    if first_char == 'c' && try_read("urvearrowleft;") { +        return Some(CharRef { +            name: "urvearrowleft;", +            characters: "\u{21b6}", +        }); +    } + +    if first_char == 'd' && try_read("oublebarwedge;") { +        return Some(CharRef { +            name: "oublebarwedge;", +            characters: "\u{2306}", +        }); +    } + +    if first_char == 'd' && try_read("owndownarrows;") { +        return Some(CharRef { +            name: "owndownarrows;", +            characters: "\u{21ca}", +        }); +    } + +    if first_char == 'h' && try_read("ookrightarrow;") { +        return Some(CharRef { +            name: "ookrightarrow;", +            characters: "\u{21aa}", +        }); +    } + +    if first_char == 'l' && try_read("eftleftarrows;") { +        return Some(CharRef { +            name: "eftleftarrows;", +            characters: "\u{21c7}", +        }); +    } + +    if first_char == 'l' && try_read("eftrightarrow;") { +        return Some(CharRef { +            name: "eftrightarrow;", +            characters: "\u{2194}", +        }); +    } + +    if first_char == 'l' && try_read("eftthreetimes;") { +        return Some(CharRef { +            name: "eftthreetimes;", +            characters: "\u{22cb}", +        }); +    } + +    if first_char == 'l' && try_read("ongrightarrow;") { +        return Some(CharRef { +            name: "ongrightarrow;", +            characters: "\u{27f6}", +        }); +    } + +    if first_char == 'l' && try_read("ooparrowright;") { +        return Some(CharRef { +            name: "ooparrowright;", +            characters: "\u{21ac}", +        }); +    } + +    if first_char == 'n' && try_read("shortparallel;") { +        return Some(CharRef { +            name: "shortparallel;", +            characters: "\u{2226}", +        }); +    } + +    if first_char == 'n' && try_read("triangleright;") { +        return Some(CharRef { +            name: "triangleright;", +            characters: "\u{22eb}", +        }); +    } + +    if first_char == 'r' && try_read("ightarrowtail;") { +        return Some(CharRef { +            name: "ightarrowtail;", +            characters: "\u{21a3}", +        }); +    } + +    if first_char == 'r' && try_read("ightharpoonup;") { +        return Some(CharRef { +            name: "ightharpoonup;", +            characters: "\u{21c0}", +        }); +    } + +    if first_char == 't' && try_read("rianglelefteq;") { +        return Some(CharRef { +            name: "rianglelefteq;", +            characters: "\u{22b4}", +        }); +    } + +    if first_char == 'u' && try_read("pharpoonright;") { +        return Some(CharRef { +            name: "pharpoonright;", +            characters: "\u{21be}", +        }); +    } + +    if first_char == 'A' && try_read("pplyFunction;") { +        return Some(CharRef { +            name: "pplyFunction;", +            characters: "\u{2061}", +        }); +    } + +    if first_char == 'D' && try_read("ifferentialD;") { +        return Some(CharRef { +            name: "ifferentialD;", +            characters: "\u{2146}", +        }); +    } + +    if first_char == 'D' && try_read("oubleLeftTee;") { +        return Some(CharRef { +            name: "oubleLeftTee;", +            characters: "\u{2ae4}", +        }); +    } + +    if first_char == 'D' && try_read("oubleUpArrow;") { +        return Some(CharRef { +            name: "oubleUpArrow;", +            characters: "\u{21d1}", +        }); +    } + +    if first_char == 'L' && try_read("eftTeeVector;") { +        return Some(CharRef { +            name: "eftTeeVector;", +            characters: "\u{295a}", +        }); +    } + +    if first_char == 'L' && try_read("eftVectorBar;") { +        return Some(CharRef { +            name: "eftVectorBar;", +            characters: "\u{2952}", +        }); +    } + +    if first_char == 'L' && try_read("essFullEqual;") { +        return Some(CharRef { +            name: "essFullEqual;", +            characters: "\u{2266}", +        }); +    } + +    if first_char == 'L' && try_read("ongLeftArrow;") { +        return Some(CharRef { +            name: "ongLeftArrow;", +            characters: "\u{27f5}", +        }); +    } + +    if first_char == 'L' && try_read("ongleftarrow;") { +        return Some(CharRef { +            name: "ongleftarrow;", +            characters: "\u{27f8}", +        }); +    } + +    if first_char == 'N' && try_read("otEqualTilde;") { +        return Some(CharRef { +            name: "otEqualTilde;", +            characters: "\u{2242}\u{338}", +        }); +    } + +    if first_char == 'N' && try_read("otTildeEqual;") { +        return Some(CharRef { +            name: "otTildeEqual;", +            characters: "\u{2244}", +        }); +    } + +    if first_char == 'N' && try_read("otTildeTilde;") { +        return Some(CharRef { +            name: "otTildeTilde;", +            characters: "\u{2249}", +        }); +    } + +    if first_char == 'P' && try_read("oincareplane;") { +        return Some(CharRef { +            name: "oincareplane;", +            characters: "\u{210c}", +        }); +    } + +    if first_char == 'P' && try_read("recedesEqual;") { +        return Some(CharRef { +            name: "recedesEqual;", +            characters: "\u{2aaf}", +        }); +    } + +    if first_char == 'P' && try_read("recedesTilde;") { +        return Some(CharRef { +            name: "recedesTilde;", +            characters: "\u{227e}", +        }); +    } + +    if first_char == 'R' && try_read("ightArrowBar;") { +        return Some(CharRef { +            name: "ightArrowBar;", +            characters: "\u{21e5}", +        }); +    } + +    if first_char == 'R' && try_read("ightTeeArrow;") { +        return Some(CharRef { +            name: "ightTeeArrow;", +            characters: "\u{21a6}", +        }); +    } + +    if first_char == 'R' && try_read("ightTriangle;") { +        return Some(CharRef { +            name: "ightTriangle;", +            characters: "\u{22b3}", +        }); +    } + +    if first_char == 'R' && try_read("ightUpVector;") { +        return Some(CharRef { +            name: "ightUpVector;", +            characters: "\u{21be}", +        }); +    } + +    if first_char == 'S' && try_read("ucceedsEqual;") { +        return Some(CharRef { +            name: "ucceedsEqual;", +            characters: "\u{2ab0}", +        }); +    } + +    if first_char == 'S' && try_read("ucceedsTilde;") { +        return Some(CharRef { +            name: "ucceedsTilde;", +            characters: "\u{227f}", +        }); +    } + +    if first_char == 'S' && try_read("upersetEqual;") { +        return Some(CharRef { +            name: "upersetEqual;", +            characters: "\u{2287}", +        }); +    } + +    if first_char == 'U' && try_read("pEquilibrium;") { +        return Some(CharRef { +            name: "pEquilibrium;", +            characters: "\u{296e}", +        }); +    } + +    if first_char == 'V' && try_read("erticalTilde;") { +        return Some(CharRef { +            name: "erticalTilde;", +            characters: "\u{2240}", +        }); +    } + +    if first_char == 'V' && try_read("eryThinSpace;") { +        return Some(CharRef { +            name: "eryThinSpace;", +            characters: "\u{200a}", +        }); +    } + +    if first_char == 'b' && try_read("igtriangleup;") { +        return Some(CharRef { +            name: "igtriangleup;", +            characters: "\u{25b3}", +        }); +    } + +    if first_char == 'b' && try_read("lacktriangle;") { +        return Some(CharRef { +            name: "lacktriangle;", +            characters: "\u{25b4}", +        }); +    } + +    if first_char == 'd' && try_read("ivideontimes;") { +        return Some(CharRef { +            name: "ivideontimes;", +            characters: "\u{22c7}", +        }); +    } + +    if first_char == 'f' && try_read("allingdotseq;") { +        return Some(CharRef { +            name: "allingdotseq;", +            characters: "\u{2252}", +        }); +    } + +    if first_char == 'h' && try_read("ookleftarrow;") { +        return Some(CharRef { +            name: "ookleftarrow;", +            characters: "\u{21a9}", +        }); +    } + +    if first_char == 'l' && try_read("eftarrowtail;") { +        return Some(CharRef { +            name: "eftarrowtail;", +            characters: "\u{21a2}", +        }); +    } + +    if first_char == 'l' && try_read("eftharpoonup;") { +        return Some(CharRef { +            name: "eftharpoonup;", +            characters: "\u{21bc}", +        }); +    } + +    if first_char == 'l' && try_read("ongleftarrow;") { +        return Some(CharRef { +            name: "ongleftarrow;", +            characters: "\u{27f5}", +        }); +    } + +    if first_char == 'l' && try_read("ooparrowleft;") { +        return Some(CharRef { +            name: "ooparrowleft;", +            characters: "\u{21ab}", +        }); +    } + +    if first_char == 'm' && try_read("easuredangle;") { +        return Some(CharRef { +            name: "easuredangle;", +            characters: "\u{2221}", +        }); +    } + +    if first_char == 'n' && try_read("triangleleft;") { +        return Some(CharRef { +            name: "triangleleft;", +            characters: "\u{22ea}", +        }); +    } + +    if first_char == 's' && try_read("hortparallel;") { +        return Some(CharRef { +            name: "hortparallel;", +            characters: "\u{2225}", +        }); +    } + +    if first_char == 's' && try_read("mallsetminus;") { +        return Some(CharRef { +            name: "mallsetminus;", +            characters: "\u{2216}", +        }); +    } + +    if first_char == 't' && try_read("riangleright;") { +        return Some(CharRef { +            name: "riangleright;", +            characters: "\u{25b9}", +        }); +    } + +    if first_char == 'u' && try_read("pharpoonleft;") { +        return Some(CharRef { +            name: "pharpoonleft;", +            characters: "\u{21bf}", +        }); +    } + +    if first_char == 'v' && try_read("arsubsetneqq;") { +        return Some(CharRef { +            name: "arsubsetneqq;", +            characters: "\u{2acb}\u{fe00}", +        }); +    } + +    if first_char == 'v' && try_read("arsupsetneqq;") { +        return Some(CharRef { +            name: "arsupsetneqq;", +            characters: "\u{2acc}\u{fe00}", +        }); +    } + +    if first_char == 'D' && try_read("ownArrowBar;") { +        return Some(CharRef { +            name: "ownArrowBar;", +            characters: "\u{2913}", +        }); +    } + +    if first_char == 'D' && try_read("ownTeeArrow;") { +        return Some(CharRef { +            name: "ownTeeArrow;", +            characters: "\u{21a7}", +        }); +    } + +    if first_char == 'E' && try_read("xponentialE;") { +        return Some(CharRef { +            name: "xponentialE;", +            characters: "\u{2147}", +        }); +    } + +    if first_char == 'G' && try_read("reaterEqual;") { +        return Some(CharRef { +            name: "reaterEqual;", +            characters: "\u{2265}", +        }); +    } + +    if first_char == 'G' && try_read("reaterTilde;") { +        return Some(CharRef { +            name: "reaterTilde;", +            characters: "\u{2273}", +        }); +    } + +    if first_char == 'H' && try_read("ilbertSpace;") { +        return Some(CharRef { +            name: "ilbertSpace;", +            characters: "\u{210b}", +        }); +    } + +    if first_char == 'H' && try_read("umpDownHump;") { +        return Some(CharRef { +            name: "umpDownHump;", +            characters: "\u{224e}", +        }); +    } + +    if first_char == 'I' && try_read("ntersection;") { +        return Some(CharRef { +            name: "ntersection;", +            characters: "\u{22c2}", +        }); +    } + +    if first_char == 'L' && try_read("eftArrowBar;") { +        return Some(CharRef { +            name: "eftArrowBar;", +            characters: "\u{21e4}", +        }); +    } + +    if first_char == 'L' && try_read("eftTeeArrow;") { +        return Some(CharRef { +            name: "eftTeeArrow;", +            characters: "\u{21a4}", +        }); +    } + +    if first_char == 'L' && try_read("eftTriangle;") { +        return Some(CharRef { +            name: "eftTriangle;", +            characters: "\u{22b2}", +        }); +    } + +    if first_char == 'L' && try_read("eftUpVector;") { +        return Some(CharRef { +            name: "eftUpVector;", +            characters: "\u{21bf}", +        }); +    } + +    if first_char == 'N' && try_read("otCongruent;") { +        return Some(CharRef { +            name: "otCongruent;", +            characters: "\u{2262}", +        }); +    } + +    if first_char == 'N' && try_read("otHumpEqual;") { +        return Some(CharRef { +            name: "otHumpEqual;", +            characters: "\u{224f}\u{338}", +        }); +    } + +    if first_char == 'N' && try_read("otLessEqual;") { +        return Some(CharRef { +            name: "otLessEqual;", +            characters: "\u{2270}", +        }); +    } + +    if first_char == 'N' && try_read("otLessTilde;") { +        return Some(CharRef { +            name: "otLessTilde;", +            characters: "\u{2274}", +        }); +    } + +    if first_char == 'P' && try_read("roportional;") { +        return Some(CharRef { +            name: "roportional;", +            characters: "\u{221d}", +        }); +    } + +    if first_char == 'R' && try_read("ightCeiling;") { +        return Some(CharRef { +            name: "ightCeiling;", +            characters: "\u{2309}", +        }); +    } + +    if first_char == 'R' && try_read("oundImplies;") { +        return Some(CharRef { +            name: "oundImplies;", +            characters: "\u{2970}", +        }); +    } + +    if first_char == 'S' && try_read("hortUpArrow;") { +        return Some(CharRef { +            name: "hortUpArrow;", +            characters: "\u{2191}", +        }); +    } + +    if first_char == 'S' && try_read("quareSubset;") { +        return Some(CharRef { +            name: "quareSubset;", +            characters: "\u{228f}", +        }); +    } + +    if first_char == 'U' && try_read("nderBracket;") { +        return Some(CharRef { +            name: "nderBracket;", +            characters: "\u{23b5}", +        }); +    } + +    if first_char == 'V' && try_read("erticalLine;") { +        return Some(CharRef { +            name: "erticalLine;", +            characters: "\u{7c}", +        }); +    } + +    if first_char == 'b' && try_read("lacklozenge;") { +        return Some(CharRef { +            name: "lacklozenge;", +            characters: "\u{29eb}", +        }); +    } + +    if first_char == 'e' && try_read("xponentiale;") { +        return Some(CharRef { +            name: "xponentiale;", +            characters: "\u{2147}", +        }); +    } + +    if first_char == 'r' && try_read("isingdotseq;") { +        return Some(CharRef { +            name: "isingdotseq;", +            characters: "\u{2253}", +        }); +    } + +    if first_char == 't' && try_read("riangledown;") { +        return Some(CharRef { +            name: "riangledown;", +            characters: "\u{25bf}", +        }); +    } + +    if first_char == 't' && try_read("riangleleft;") { +        return Some(CharRef { +            name: "riangleleft;", +            characters: "\u{25c3}", +        }); +    } + +    if first_char == 'v' && try_read("arsubsetneq;") { +        return Some(CharRef { +            name: "arsubsetneq;", +            characters: "\u{228a}\u{fe00}", +        }); +    } + +    if first_char == 'v' && try_read("arsupsetneq;") { +        return Some(CharRef { +            name: "arsupsetneq;", +            characters: "\u{228b}\u{fe00}", +        }); +    } + +    if first_char == 'C' && try_read("ircleMinus;") { +        return Some(CharRef { +            name: "ircleMinus;", +            characters: "\u{2296}", +        }); +    } + +    if first_char == 'C' && try_read("ircleTimes;") { +        return Some(CharRef { +            name: "ircleTimes;", +            characters: "\u{2297}", +        }); +    } + +    if first_char == 'E' && try_read("quilibrium;") { +        return Some(CharRef { +            name: "quilibrium;", +            characters: "\u{21cc}", +        }); +    } + +    if first_char == 'G' && try_read("reaterLess;") { +        return Some(CharRef { +            name: "reaterLess;", +            characters: "\u{2277}", +        }); +    } + +    if first_char == 'L' && try_read("eftCeiling;") { +        return Some(CharRef { +            name: "eftCeiling;", +            characters: "\u{2308}", +        }); +    } + +    if first_char == 'L' && try_read("essGreater;") { +        return Some(CharRef { +            name: "essGreater;", +            characters: "\u{2276}", +        }); +    } + +    if first_char == 'M' && try_read("ediumSpace;") { +        return Some(CharRef { +            name: "ediumSpace;", +            characters: "\u{205f}", +        }); +    } + +    if first_char == 'N' && try_read("otLessLess;") { +        return Some(CharRef { +            name: "otLessLess;", +            characters: "\u{226a}\u{338}", +        }); +    } + +    if first_char == 'N' && try_read("otPrecedes;") { +        return Some(CharRef { +            name: "otPrecedes;", +            characters: "\u{2280}", +        }); +    } + +    if first_char == 'N' && try_read("otSucceeds;") { +        return Some(CharRef { +            name: "otSucceeds;", +            characters: "\u{2281}", +        }); +    } + +    if first_char == 'N' && try_read("otSuperset;") { +        return Some(CharRef { +            name: "otSuperset;", +            characters: "\u{2283}\u{20d2}", +        }); +    } + +    if first_char == 'O' && try_read("verBracket;") { +        return Some(CharRef { +            name: "verBracket;", +            characters: "\u{23b4}", +        }); +    } + +    if first_char == 'R' && try_read("ightVector;") { +        return Some(CharRef { +            name: "ightVector;", +            characters: "\u{21c0}", +        }); +    } + +    if first_char == 'R' && try_read("rightarrow;") { +        return Some(CharRef { +            name: "rightarrow;", +            characters: "\u{21db}", +        }); +    } + +    if first_char == 'R' && try_read("uleDelayed;") { +        return Some(CharRef { +            name: "uleDelayed;", +            characters: "\u{29f4}", +        }); +    } + +    if first_char == 'S' && try_read("mallCircle;") { +        return Some(CharRef { +            name: "mallCircle;", +            characters: "\u{2218}", +        }); +    } + +    if first_char == 'S' && try_read("quareUnion;") { +        return Some(CharRef { +            name: "quareUnion;", +            characters: "\u{2294}", +        }); +    } + +    if first_char == 'S' && try_read("ubsetEqual;") { +        return Some(CharRef { +            name: "ubsetEqual;", +            characters: "\u{2286}", +        }); +    } + +    if first_char == 'U' && try_read("pDownArrow;") { +        return Some(CharRef { +            name: "pDownArrow;", +            characters: "\u{2195}", +        }); +    } + +    if first_char == 'U' && try_read("pdownarrow;") { +        return Some(CharRef { +            name: "pdownarrow;", +            characters: "\u{21d5}", +        }); +    } + +    if first_char == 'V' && try_read("erticalBar;") { +        return Some(CharRef { +            name: "erticalBar;", +            characters: "\u{2223}", +        }); +    } + +    if first_char == 'b' && try_read("ackepsilon;") { +        return Some(CharRef { +            name: "ackepsilon;", +            characters: "\u{3f6}", +        }); +    } + +    if first_char == 'b' && try_read("lacksquare;") { +        return Some(CharRef { +            name: "lacksquare;", +            characters: "\u{25aa}", +        }); +    } + +    if first_char == 'c' && try_read("ircledcirc;") { +        return Some(CharRef { +            name: "ircledcirc;", +            characters: "\u{229a}", +        }); +    } + +    if first_char == 'c' && try_read("ircleddash;") { +        return Some(CharRef { +            name: "ircleddash;", +            characters: "\u{229d}", +        }); +    } + +    if first_char == 'c' && try_read("urlyeqprec;") { +        return Some(CharRef { +            name: "urlyeqprec;", +            characters: "\u{22de}", +        }); +    } + +    if first_char == 'c' && try_read("urlyeqsucc;") { +        return Some(CharRef { +            name: "urlyeqsucc;", +            characters: "\u{22df}", +        }); +    } + +    if first_char == 'd' && try_read("iamondsuit;") { +        return Some(CharRef { +            name: "iamondsuit;", +            characters: "\u{2666}", +        }); +    } + +    if first_char == 'e' && try_read("qslantless;") { +        return Some(CharRef { +            name: "qslantless;", +            characters: "\u{2a95}", +        }); +    } + +    if first_char == 'e' && try_read("xpectation;") { +        return Some(CharRef { +            name: "xpectation;", +            characters: "\u{2130}", +        }); +    } + +    if first_char == 'n' && try_read("Rightarrow;") { +        return Some(CharRef { +            name: "Rightarrow;", +            characters: "\u{21cf}", +        }); +    } + +    if first_char == 'n' && try_read("rightarrow;") { +        return Some(CharRef { +            name: "rightarrow;", +            characters: "\u{219b}", +        }); +    } + +    if first_char == 'p' && try_read("reccurlyeq;") { +        return Some(CharRef { +            name: "reccurlyeq;", +            characters: "\u{227c}", +        }); +    } + +    if first_char == 'p' && try_read("recnapprox;") { +        return Some(CharRef { +            name: "recnapprox;", +            characters: "\u{2ab9}", +        }); +    } + +    if first_char == 'q' && try_read("uaternions;") { +        return Some(CharRef { +            name: "uaternions;", +            characters: "\u{210d}", +        }); +    } + +    if first_char == 's' && try_read("traightphi;") { +        return Some(CharRef { +            name: "traightphi;", +            characters: "\u{3d5}", +        }); +    } + +    if first_char == 's' && try_read("ucccurlyeq;") { +        return Some(CharRef { +            name: "ucccurlyeq;", +            characters: "\u{227d}", +        }); +    } + +    if first_char == 's' && try_read("uccnapprox;") { +        return Some(CharRef { +            name: "uccnapprox;", +            characters: "\u{2aba}", +        }); +    } + +    if first_char == 't' && try_read("hickapprox;") { +        return Some(CharRef { +            name: "hickapprox;", +            characters: "\u{2248}", +        }); +    } + +    if first_char == 'u' && try_read("pdownarrow;") { +        return Some(CharRef { +            name: "pdownarrow;", +            characters: "\u{2195}", +        }); +    } + +    if first_char == 'B' && try_read("ernoullis;") { +        return Some(CharRef { +            name: "ernoullis;", +            characters: "\u{212c}", +        }); +    } + +    if first_char == 'C' && try_read("irclePlus;") { +        return Some(CharRef { +            name: "irclePlus;", +            characters: "\u{2295}", +        }); +    } + +    if first_char == 'E' && try_read("qualTilde;") { +        return Some(CharRef { +            name: "qualTilde;", +            characters: "\u{2242}", +        }); +    } + +    if first_char == 'F' && try_read("ouriertrf;") { +        return Some(CharRef { +            name: "ouriertrf;", +            characters: "\u{2131}", +        }); +    } + +    if first_char == 'I' && try_read("maginaryI;") { +        return Some(CharRef { +            name: "maginaryI;", +            characters: "\u{2148}", +        }); +    } + +    if first_char == 'L' && try_read("aplacetrf;") { +        return Some(CharRef { +            name: "aplacetrf;", +            characters: "\u{2112}", +        }); +    } + +    if first_char == 'L' && try_read("eftVector;") { +        return Some(CharRef { +            name: "eftVector;", +            characters: "\u{21bc}", +        }); +    } + +    if first_char == 'L' && try_read("leftarrow;") { +        return Some(CharRef { +            name: "leftarrow;", +            characters: "\u{21da}", +        }); +    } + +    if first_char == 'N' && try_read("otElement;") { +        return Some(CharRef { +            name: "otElement;", +            characters: "\u{2209}", +        }); +    } + +    if first_char == 'N' && try_read("otGreater;") { +        return Some(CharRef { +            name: "otGreater;", +            characters: "\u{226f}", +        }); +    } + +    if first_char == 'P' && try_read("roportion;") { +        return Some(CharRef { +            name: "roportion;", +            characters: "\u{2237}", +        }); +    } + +    if first_char == 'R' && try_read("ightArrow;") { +        return Some(CharRef { +            name: "ightArrow;", +            characters: "\u{2192}", +        }); +    } + +    if first_char == 'R' && try_read("ightFloor;") { +        return Some(CharRef { +            name: "ightFloor;", +            characters: "\u{230b}", +        }); +    } + +    if first_char == 'R' && try_read("ightarrow;") { +        return Some(CharRef { +            name: "ightarrow;", +            characters: "\u{21d2}", +        }); +    } + +    if first_char == 'T' && try_read("hickSpace;") { +        return Some(CharRef { +            name: "hickSpace;", +            characters: "\u{205f}\u{200a}", +        }); +    } + +    if first_char == 'T' && try_read("ildeEqual;") { +        return Some(CharRef { +            name: "ildeEqual;", +            characters: "\u{2243}", +        }); +    } + +    if first_char == 'T' && try_read("ildeTilde;") { +        return Some(CharRef { +            name: "ildeTilde;", +            characters: "\u{2248}", +        }); +    } + +    if first_char == 'U' && try_read("nderBrace;") { +        return Some(CharRef { +            name: "nderBrace;", +            characters: "\u{23df}", +        }); +    } + +    if first_char == 'U' && try_read("pArrowBar;") { +        return Some(CharRef { +            name: "pArrowBar;", +            characters: "\u{2912}", +        }); +    } + +    if first_char == 'U' && try_read("pTeeArrow;") { +        return Some(CharRef { +            name: "pTeeArrow;", +            characters: "\u{21a5}", +        }); +    } + +    if first_char == 'c' && try_read("ircledast;") { +        return Some(CharRef { +            name: "ircledast;", +            characters: "\u{229b}", +        }); +    } + +    if first_char == 'c' && try_read("omplement;") { +        return Some(CharRef { +            name: "omplement;", +            characters: "\u{2201}", +        }); +    } + +    if first_char == 'c' && try_read("urlywedge;") { +        return Some(CharRef { +            name: "urlywedge;", +            characters: "\u{22cf}", +        }); +    } + +    if first_char == 'e' && try_read("qslantgtr;") { +        return Some(CharRef { +            name: "qslantgtr;", +            characters: "\u{2a96}", +        }); +    } + +    if first_char == 'g' && try_read("treqqless;") { +        return Some(CharRef { +            name: "treqqless;", +            characters: "\u{2a8c}", +        }); +    } + +    if first_char == 'l' && try_read("essapprox;") { +        return Some(CharRef { +            name: "essapprox;", +            characters: "\u{2a85}", +        }); +    } + +    if first_char == 'l' && try_read("esseqqgtr;") { +        return Some(CharRef { +            name: "esseqqgtr;", +            characters: "\u{2a8b}", +        }); +    } + +    if first_char == 'l' && try_read("moustache;") { +        return Some(CharRef { +            name: "moustache;", +            characters: "\u{23b0}", +        }); +    } + +    if first_char == 'l' && try_read("ongmapsto;") { +        return Some(CharRef { +            name: "ongmapsto;", +            characters: "\u{27fc}", +        }); +    } + +    if first_char == 'm' && try_read("apstodown;") { +        return Some(CharRef { +            name: "apstodown;", +            characters: "\u{21a7}", +        }); +    } + +    if first_char == 'm' && try_read("apstoleft;") { +        return Some(CharRef { +            name: "apstoleft;", +            characters: "\u{21a4}", +        }); +    } + +    if first_char == 'n' && try_read("Leftarrow;") { +        return Some(CharRef { +            name: "Leftarrow;", +            characters: "\u{21cd}", +        }); +    } + +    if first_char == 'n' && try_read("leftarrow;") { +        return Some(CharRef { +            name: "leftarrow;", +            characters: "\u{219a}", +        }); +    } + +    if first_char == 'n' && try_read("subseteqq;") { +        return Some(CharRef { +            name: "subseteqq;", +            characters: "\u{2ac5}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("supseteqq;") { +        return Some(CharRef { +            name: "supseteqq;", +            characters: "\u{2ac6}\u{338}", +        }); +    } + +    if first_char == 'p' && try_read("recapprox;") { +        return Some(CharRef { +            name: "recapprox;", +            characters: "\u{2ab7}", +        }); +    } + +    if first_char == 'r' && try_read("ightarrow;") { +        return Some(CharRef { +            name: "ightarrow;", +            characters: "\u{2192}", +        }); +    } + +    if first_char == 'r' && try_read("moustache;") { +        return Some(CharRef { +            name: "moustache;", +            characters: "\u{23b1}", +        }); +    } + +    if first_char == 's' && try_read("qsubseteq;") { +        return Some(CharRef { +            name: "qsubseteq;", +            characters: "\u{2291}", +        }); +    } + +    if first_char == 's' && try_read("qsupseteq;") { +        return Some(CharRef { +            name: "qsupseteq;", +            characters: "\u{2292}", +        }); +    } + +    if first_char == 's' && try_read("ubsetneqq;") { +        return Some(CharRef { +            name: "ubsetneqq;", +            characters: "\u{2acb}", +        }); +    } + +    if first_char == 's' && try_read("uccapprox;") { +        return Some(CharRef { +            name: "uccapprox;", +            characters: "\u{2ab8}", +        }); +    } + +    if first_char == 's' && try_read("upsetneqq;") { +        return Some(CharRef { +            name: "upsetneqq;", +            characters: "\u{2acc}", +        }); +    } + +    if first_char == 'u' && try_read("puparrows;") { +        return Some(CharRef { +            name: "puparrows;", +            characters: "\u{21c8}", +        }); +    } + +    if first_char == 'v' && try_read("arepsilon;") { +        return Some(CharRef { +            name: "arepsilon;", +            characters: "\u{3f5}", +        }); +    } + +    if first_char == 'v' && try_read("arnothing;") { +        return Some(CharRef { +            name: "arnothing;", +            characters: "\u{2205}", +        }); +    } + +    if first_char == 'B' && try_read("ackslash;") { +        return Some(CharRef { +            name: "ackslash;", +            characters: "\u{2216}", +        }); +    } + +    if first_char == 'C' && try_read("enterDot;") { +        return Some(CharRef { +            name: "enterDot;", +            characters: "\u{b7}", +        }); +    } + +    if first_char == 'C' && try_read("ircleDot;") { +        return Some(CharRef { +            name: "ircleDot;", +            characters: "\u{2299}", +        }); +    } + +    if first_char == 'C' && try_read("ongruent;") { +        return Some(CharRef { +            name: "ongruent;", +            characters: "\u{2261}", +        }); +    } + +    if first_char == 'C' && try_read("oproduct;") { +        return Some(CharRef { +            name: "oproduct;", +            characters: "\u{2210}", +        }); +    } + +    if first_char == 'D' && try_read("oubleDot;") { +        return Some(CharRef { +            name: "oubleDot;", +            characters: "\u{a8}", +        }); +    } + +    if first_char == 'D' && try_read("ownArrow;") { +        return Some(CharRef { +            name: "ownArrow;", +            characters: "\u{2193}", +        }); +    } + +    if first_char == 'D' && try_read("ownBreve;") { +        return Some(CharRef { +            name: "ownBreve;", +            characters: "\u{311}", +        }); +    } + +    if first_char == 'D' && try_read("ownarrow;") { +        return Some(CharRef { +            name: "ownarrow;", +            characters: "\u{21d3}", +        }); +    } + +    if first_char == 'H' && try_read("umpEqual;") { +        return Some(CharRef { +            name: "umpEqual;", +            characters: "\u{224f}", +        }); +    } + +    if first_char == 'L' && try_read("eftArrow;") { +        return Some(CharRef { +            name: "eftArrow;", +            characters: "\u{2190}", +        }); +    } + +    if first_char == 'L' && try_read("eftFloor;") { +        return Some(CharRef { +            name: "eftFloor;", +            characters: "\u{230a}", +        }); +    } + +    if first_char == 'L' && try_read("eftarrow;") { +        return Some(CharRef { +            name: "eftarrow;", +            characters: "\u{21d0}", +        }); +    } + +    if first_char == 'L' && try_read("essTilde;") { +        return Some(CharRef { +            name: "essTilde;", +            characters: "\u{2272}", +        }); +    } + +    if first_char == 'M' && try_read("ellintrf;") { +        return Some(CharRef { +            name: "ellintrf;", +            characters: "\u{2133}", +        }); +    } + +    if first_char == 'M' && try_read("inusPlus;") { +        return Some(CharRef { +            name: "inusPlus;", +            characters: "\u{2213}", +        }); +    } + +    if first_char == 'N' && try_read("otCupCap;") { +        return Some(CharRef { +            name: "otCupCap;", +            characters: "\u{226d}", +        }); +    } + +    if first_char == 'N' && try_read("otExists;") { +        return Some(CharRef { +            name: "otExists;", +            characters: "\u{2204}", +        }); +    } + +    if first_char == 'N' && try_read("otSubset;") { +        return Some(CharRef { +            name: "otSubset;", +            characters: "\u{2282}\u{20d2}", +        }); +    } + +    if first_char == 'O' && try_read("verBrace;") { +        return Some(CharRef { +            name: "verBrace;", +            characters: "\u{23de}", +        }); +    } + +    if first_char == 'P' && try_read("lusMinus;") { +        return Some(CharRef { +            name: "lusMinus;", +            characters: "\u{b1}", +        }); +    } + +    if first_char == 'T' && try_read("herefore;") { +        return Some(CharRef { +            name: "herefore;", +            characters: "\u{2234}", +        }); +    } + +    if first_char == 'T' && try_read("hinSpace;") { +        return Some(CharRef { +            name: "hinSpace;", +            characters: "\u{2009}", +        }); +    } + +    if first_char == 'T' && try_read("ripleDot;") { +        return Some(CharRef { +            name: "ripleDot;", +            characters: "\u{20db}", +        }); +    } + +    if first_char == 'U' && try_read("nionPlus;") { +        return Some(CharRef { +            name: "nionPlus;", +            characters: "\u{228e}", +        }); +    } + +    if first_char == 'b' && try_read("ackprime;") { +        return Some(CharRef { +            name: "ackprime;", +            characters: "\u{2035}", +        }); +    } + +    if first_char == 'b' && try_read("acksimeq;") { +        return Some(CharRef { +            name: "acksimeq;", +            characters: "\u{22cd}", +        }); +    } + +    if first_char == 'b' && try_read("igotimes;") { +        return Some(CharRef { +            name: "igotimes;", +            characters: "\u{2a02}", +        }); +    } + +    if first_char == 'c' && try_read("enterdot;") { +        return Some(CharRef { +            name: "enterdot;", +            characters: "\u{b7}", +        }); +    } + +    if first_char == 'c' && try_read("heckmark;") { +        return Some(CharRef { +            name: "heckmark;", +            characters: "\u{2713}", +        }); +    } + +    if first_char == 'c' && try_read("omplexes;") { +        return Some(CharRef { +            name: "omplexes;", +            characters: "\u{2102}", +        }); +    } + +    if first_char == 'd' && try_read("otsquare;") { +        return Some(CharRef { +            name: "otsquare;", +            characters: "\u{22a1}", +        }); +    } + +    if first_char == 'd' && try_read("ownarrow;") { +        return Some(CharRef { +            name: "ownarrow;", +            characters: "\u{2193}", +        }); +    } + +    if first_char == 'g' && try_read("trapprox;") { +        return Some(CharRef { +            name: "trapprox;", +            characters: "\u{2a86}", +        }); +    } + +    if first_char == 'g' && try_read("treqless;") { +        return Some(CharRef { +            name: "treqless;", +            characters: "\u{22db}", +        }); +    } + +    if first_char == 'g' && try_read("vertneqq;") { +        return Some(CharRef { +            name: "vertneqq;", +            characters: "\u{2269}\u{fe00}", +        }); +    } + +    if first_char == 'h' && try_read("eartsuit;") { +        return Some(CharRef { +            name: "eartsuit;", +            characters: "\u{2665}", +        }); +    } + +    if first_char == 'l' && try_read("eftarrow;") { +        return Some(CharRef { +            name: "eftarrow;", +            characters: "\u{2190}", +        }); +    } + +    if first_char == 'l' && try_read("esseqgtr;") { +        return Some(CharRef { +            name: "esseqgtr;", +            characters: "\u{22da}", +        }); +    } + +    if first_char == 'l' && try_read("vertneqq;") { +        return Some(CharRef { +            name: "vertneqq;", +            characters: "\u{2268}\u{fe00}", +        }); +    } + +    if first_char == 'n' && try_read("geqslant;") { +        return Some(CharRef { +            name: "geqslant;", +            characters: "\u{2a7e}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("leqslant;") { +        return Some(CharRef { +            name: "leqslant;", +            characters: "\u{2a7d}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("parallel;") { +        return Some(CharRef { +            name: "parallel;", +            characters: "\u{2226}", +        }); +    } + +    if first_char == 'n' && try_read("shortmid;") { +        return Some(CharRef { +            name: "shortmid;", +            characters: "\u{2224}", +        }); +    } + +    if first_char == 'n' && try_read("subseteq;") { +        return Some(CharRef { +            name: "subseteq;", +            characters: "\u{2288}", +        }); +    } + +    if first_char == 'n' && try_read("supseteq;") { +        return Some(CharRef { +            name: "supseteq;", +            characters: "\u{2289}", +        }); +    } + +    if first_char == 'p' && try_read("itchfork;") { +        return Some(CharRef { +            name: "itchfork;", +            characters: "\u{22d4}", +        }); +    } + +    if first_char == 'r' && try_read("ationals;") { +        return Some(CharRef { +            name: "ationals;", +            characters: "\u{211a}", +        }); +    } + +    if first_char == 's' && try_read("padesuit;") { +        return Some(CharRef { +            name: "padesuit;", +            characters: "\u{2660}", +        }); +    } + +    if first_char == 's' && try_read("ubseteqq;") { +        return Some(CharRef { +            name: "ubseteqq;", +            characters: "\u{2ac5}", +        }); +    } + +    if first_char == 's' && try_read("ubsetneq;") { +        return Some(CharRef { +            name: "ubsetneq;", +            characters: "\u{228a}", +        }); +    } + +    if first_char == 's' && try_read("upseteqq;") { +        return Some(CharRef { +            name: "upseteqq;", +            characters: "\u{2ac6}", +        }); +    } + +    if first_char == 's' && try_read("upsetneq;") { +        return Some(CharRef { +            name: "upsetneq;", +            characters: "\u{228b}", +        }); +    } + +    if first_char == 't' && try_read("herefore;") { +        return Some(CharRef { +            name: "herefore;", +            characters: "\u{2234}", +        }); +    } + +    if first_char == 't' && try_read("riangleq;") { +        return Some(CharRef { +            name: "riangleq;", +            characters: "\u{225c}", +        }); +    } + +    if first_char == 'v' && try_read("arpropto;") { +        return Some(CharRef { +            name: "arpropto;", +            characters: "\u{221d}", +        }); +    } + +    if first_char == 'D' && try_read("Dotrahd;") { +        return Some(CharRef { +            name: "Dotrahd;", +            characters: "\u{2911}", +        }); +    } + +    if first_char == 'D' && try_read("otEqual;") { +        return Some(CharRef { +            name: "otEqual;", +            characters: "\u{2250}", +        }); +    } + +    if first_char == 'I' && try_read("ntegral;") { +        return Some(CharRef { +            name: "ntegral;", +            characters: "\u{222b}", +        }); +    } + +    if first_char == 'L' && try_read("essLess;") { +        return Some(CharRef { +            name: "essLess;", +            characters: "\u{2aa1}", +        }); +    } + +    if first_char == 'N' && try_read("otEqual;") { +        return Some(CharRef { +            name: "otEqual;", +            characters: "\u{2260}", +        }); +    } + +    if first_char == 'N' && try_read("otTilde;") { +        return Some(CharRef { +            name: "otTilde;", +            characters: "\u{2241}", +        }); +    } + +    if first_char == 'P' && try_read("artialD;") { +        return Some(CharRef { +            name: "artialD;", +            characters: "\u{2202}", +        }); +    } + +    if first_char == 'P' && try_read("recedes;") { +        return Some(CharRef { +            name: "recedes;", +            characters: "\u{227a}", +        }); +    } + +    if first_char == 'R' && try_read("ightTee;") { +        return Some(CharRef { +            name: "ightTee;", +            characters: "\u{22a2}", +        }); +    } + +    if first_char == 'S' && try_read("ucceeds;") { +        return Some(CharRef { +            name: "ucceeds;", +            characters: "\u{227b}", +        }); +    } + +    if first_char == 'S' && try_read("uchThat;") { +        return Some(CharRef { +            name: "uchThat;", +            characters: "\u{220b}", +        }); +    } + +    if first_char == 'S' && try_read("uperset;") { +        return Some(CharRef { +            name: "uperset;", +            characters: "\u{2283}", +        }); +    } + +    if first_char == 'U' && try_read("arrocir;") { +        return Some(CharRef { +            name: "arrocir;", +            characters: "\u{2949}", +        }); +    } + +    if first_char == 'U' && try_read("nderBar;") { +        return Some(CharRef { +            name: "nderBar;", +            characters: "\u{5f}", +        }); +    } + +    if first_char == 'a' && try_read("ndslope;") { +        return Some(CharRef { +            name: "ndslope;", +            characters: "\u{2a58}", +        }); +    } + +    if first_char == 'a' && try_read("ngmsdaa;") { +        return Some(CharRef { +            name: "ngmsdaa;", +            characters: "\u{29a8}", +        }); +    } + +    if first_char == 'a' && try_read("ngmsdab;") { +        return Some(CharRef { +            name: "ngmsdab;", +            characters: "\u{29a9}", +        }); +    } + +    if first_char == 'a' && try_read("ngmsdac;") { +        return Some(CharRef { +            name: "ngmsdac;", +            characters: "\u{29aa}", +        }); +    } + +    if first_char == 'a' && try_read("ngmsdad;") { +        return Some(CharRef { +            name: "ngmsdad;", +            characters: "\u{29ab}", +        }); +    } + +    if first_char == 'a' && try_read("ngmsdae;") { +        return Some(CharRef { +            name: "ngmsdae;", +            characters: "\u{29ac}", +        }); +    } + +    if first_char == 'a' && try_read("ngmsdaf;") { +        return Some(CharRef { +            name: "ngmsdaf;", +            characters: "\u{29ad}", +        }); +    } + +    if first_char == 'a' && try_read("ngmsdag;") { +        return Some(CharRef { +            name: "ngmsdag;", +            characters: "\u{29ae}", +        }); +    } + +    if first_char == 'a' && try_read("ngmsdah;") { +        return Some(CharRef { +            name: "ngmsdah;", +            characters: "\u{29af}", +        }); +    } + +    if first_char == 'a' && try_read("ngrtvbd;") { +        return Some(CharRef { +            name: "ngrtvbd;", +            characters: "\u{299d}", +        }); +    } + +    if first_char == 'a' && try_read("pproxeq;") { +        return Some(CharRef { +            name: "pproxeq;", +            characters: "\u{224a}", +        }); +    } + +    if first_char == 'a' && try_read("wconint;") { +        return Some(CharRef { +            name: "wconint;", +            characters: "\u{2233}", +        }); +    } + +    if first_char == 'b' && try_read("ackcong;") { +        return Some(CharRef { +            name: "ackcong;", +            characters: "\u{224c}", +        }); +    } + +    if first_char == 'b' && try_read("arwedge;") { +        return Some(CharRef { +            name: "arwedge;", +            characters: "\u{2305}", +        }); +    } + +    if first_char == 'b' && try_read("brktbrk;") { +        return Some(CharRef { +            name: "brktbrk;", +            characters: "\u{23b6}", +        }); +    } + +    if first_char == 'b' && try_read("igoplus;") { +        return Some(CharRef { +            name: "igoplus;", +            characters: "\u{2a01}", +        }); +    } + +    if first_char == 'b' && try_read("igsqcup;") { +        return Some(CharRef { +            name: "igsqcup;", +            characters: "\u{2a06}", +        }); +    } + +    if first_char == 'b' && try_read("iguplus;") { +        return Some(CharRef { +            name: "iguplus;", +            characters: "\u{2a04}", +        }); +    } + +    if first_char == 'b' && try_read("igwedge;") { +        return Some(CharRef { +            name: "igwedge;", +            characters: "\u{22c0}", +        }); +    } + +    if first_char == 'b' && try_read("oxminus;") { +        return Some(CharRef { +            name: "oxminus;", +            characters: "\u{229f}", +        }); +    } + +    if first_char == 'b' && try_read("oxtimes;") { +        return Some(CharRef { +            name: "oxtimes;", +            characters: "\u{22a0}", +        }); +    } + +    if first_char == 'b' && try_read("solhsub;") { +        return Some(CharRef { +            name: "solhsub;", +            characters: "\u{27c8}", +        }); +    } + +    if first_char == 'c' && try_read("apbrcup;") { +        return Some(CharRef { +            name: "apbrcup;", +            characters: "\u{2a49}", +        }); +    } + +    if first_char == 'c' && try_read("ircledR;") { +        return Some(CharRef { +            name: "ircledR;", +            characters: "\u{ae}", +        }); +    } + +    if first_char == 'c' && try_read("ircledS;") { +        return Some(CharRef { +            name: "ircledS;", +            characters: "\u{24c8}", +        }); +    } + +    if first_char == 'c' && try_read("irfnint;") { +        return Some(CharRef { +            name: "irfnint;", +            characters: "\u{2a10}", +        }); +    } + +    if first_char == 'c' && try_read("lubsuit;") { +        return Some(CharRef { +            name: "lubsuit;", +            characters: "\u{2663}", +        }); +    } + +    if first_char == 'c' && try_read("upbrcap;") { +        return Some(CharRef { +            name: "upbrcap;", +            characters: "\u{2a48}", +        }); +    } + +    if first_char == 'c' && try_read("urlyvee;") { +        return Some(CharRef { +            name: "urlyvee;", +            characters: "\u{22ce}", +        }); +    } + +    if first_char == 'c' && try_read("wconint;") { +        return Some(CharRef { +            name: "wconint;", +            characters: "\u{2232}", +        }); +    } + +    if first_char == 'd' && try_read("oteqdot;") { +        return Some(CharRef { +            name: "oteqdot;", +            characters: "\u{2251}", +        }); +    } + +    if first_char == 'd' && try_read("otminus;") { +        return Some(CharRef { +            name: "otminus;", +            characters: "\u{2238}", +        }); +    } + +    if first_char == 'd' && try_read("rbkarow;") { +        return Some(CharRef { +            name: "rbkarow;", +            characters: "\u{2910}", +        }); +    } + +    if first_char == 'd' && try_read("zigrarr;") { +        return Some(CharRef { +            name: "zigrarr;", +            characters: "\u{27ff}", +        }); +    } + +    if first_char == 'e' && try_read("linters;") { +        return Some(CharRef { +            name: "linters;", +            characters: "\u{23e7}", +        }); +    } + +    if first_char == 'e' && try_read("mptyset;") { +        return Some(CharRef { +            name: "mptyset;", +            characters: "\u{2205}", +        }); +    } + +    if first_char == 'e' && try_read("qvparsl;") { +        return Some(CharRef { +            name: "qvparsl;", +            characters: "\u{29e5}", +        }); +    } + +    if first_char == 'f' && try_read("partint;") { +        return Some(CharRef { +            name: "partint;", +            characters: "\u{2a0d}", +        }); +    } + +    if first_char == 'g' && try_read("eqslant;") { +        return Some(CharRef { +            name: "eqslant;", +            characters: "\u{2a7e}", +        }); +    } + +    if first_char == 'g' && try_read("esdotol;") { +        return Some(CharRef { +            name: "esdotol;", +            characters: "\u{2a84}", +        }); +    } + +    if first_char == 'g' && try_read("napprox;") { +        return Some(CharRef { +            name: "napprox;", +            characters: "\u{2a8a}", +        }); +    } + +    if first_char == 'h' && try_read("ksearow;") { +        return Some(CharRef { +            name: "ksearow;", +            characters: "\u{2925}", +        }); +    } + +    if first_char == 'h' && try_read("kswarow;") { +        return Some(CharRef { +            name: "kswarow;", +            characters: "\u{2926}", +        }); +    } + +    if first_char == 'i' && try_read("magline;") { +        return Some(CharRef { +            name: "magline;", +            characters: "\u{2110}", +        }); +    } + +    if first_char == 'i' && try_read("magpart;") { +        return Some(CharRef { +            name: "magpart;", +            characters: "\u{2111}", +        }); +    } + +    if first_char == 'i' && try_read("nfintie;") { +        return Some(CharRef { +            name: "nfintie;", +            characters: "\u{29dd}", +        }); +    } + +    if first_char == 'i' && try_read("ntegers;") { +        return Some(CharRef { +            name: "ntegers;", +            characters: "\u{2124}", +        }); +    } + +    if first_char == 'i' && try_read("ntercal;") { +        return Some(CharRef { +            name: "ntercal;", +            characters: "\u{22ba}", +        }); +    } + +    if first_char == 'i' && try_read("ntlarhk;") { +        return Some(CharRef { +            name: "ntlarhk;", +            characters: "\u{2a17}", +        }); +    } + +    if first_char == 'l' && try_read("aemptyv;") { +        return Some(CharRef { +            name: "aemptyv;", +            characters: "\u{29b4}", +        }); +    } + +    if first_char == 'l' && try_read("drushar;") { +        return Some(CharRef { +            name: "drushar;", +            characters: "\u{294b}", +        }); +    } + +    if first_char == 'l' && try_read("eqslant;") { +        return Some(CharRef { +            name: "eqslant;", +            characters: "\u{2a7d}", +        }); +    } + +    if first_char == 'l' && try_read("esdotor;") { +        return Some(CharRef { +            name: "esdotor;", +            characters: "\u{2a83}", +        }); +    } + +    if first_char == 'l' && try_read("lcorner;") { +        return Some(CharRef { +            name: "lcorner;", +            characters: "\u{231e}", +        }); +    } + +    if first_char == 'l' && try_read("napprox;") { +        return Some(CharRef { +            name: "napprox;", +            characters: "\u{2a89}", +        }); +    } + +    if first_char == 'l' && try_read("rcorner;") { +        return Some(CharRef { +            name: "rcorner;", +            characters: "\u{231f}", +        }); +    } + +    if first_char == 'l' && try_read("urdshar;") { +        return Some(CharRef { +            name: "urdshar;", +            characters: "\u{294a}", +        }); +    } + +    if first_char == 'm' && try_read("apstoup;") { +        return Some(CharRef { +            name: "apstoup;", +            characters: "\u{21a5}", +        }); +    } + +    if first_char == 'm' && try_read("ultimap;") { +        return Some(CharRef { +            name: "ultimap;", +            characters: "\u{22b8}", +        }); +    } + +    if first_char == 'n' && try_read("aturals;") { +        return Some(CharRef { +            name: "aturals;", +            characters: "\u{2115}", +        }); +    } + +    if first_char == 'n' && try_read("congdot;") { +        return Some(CharRef { +            name: "congdot;", +            characters: "\u{2a6d}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("otindot;") { +        return Some(CharRef { +            name: "otindot;", +            characters: "\u{22f5}\u{338}", +        }); +    } + +    if first_char == 'o' && try_read("timesas;") { +        return Some(CharRef { +            name: "timesas;", +            characters: "\u{2a36}", +        }); +    } + +    if first_char == 'p' && try_read("arallel;") { +        return Some(CharRef { +            name: "arallel;", +            characters: "\u{2225}", +        }); +    } + +    if first_char == 'p' && try_read("lusacir;") { +        return Some(CharRef { +            name: "lusacir;", +            characters: "\u{2a23}", +        }); +    } + +    if first_char == 'p' && try_read("ointint;") { +        return Some(CharRef { +            name: "ointint;", +            characters: "\u{2a15}", +        }); +    } + +    if first_char == 'p' && try_read("recneqq;") { +        return Some(CharRef { +            name: "recneqq;", +            characters: "\u{2ab5}", +        }); +    } + +    if first_char == 'p' && try_read("recnsim;") { +        return Some(CharRef { +            name: "recnsim;", +            characters: "\u{22e8}", +        }); +    } + +    if first_char == 'p' && try_read("rofalar;") { +        return Some(CharRef { +            name: "rofalar;", +            characters: "\u{232e}", +        }); +    } + +    if first_char == 'p' && try_read("rofline;") { +        return Some(CharRef { +            name: "rofline;", +            characters: "\u{2312}", +        }); +    } + +    if first_char == 'p' && try_read("rofsurf;") { +        return Some(CharRef { +            name: "rofsurf;", +            characters: "\u{2313}", +        }); +    } + +    if first_char == 'r' && try_read("aemptyv;") { +        return Some(CharRef { +            name: "aemptyv;", +            characters: "\u{29b3}", +        }); +    } + +    if first_char == 'r' && try_read("ealpart;") { +        return Some(CharRef { +            name: "ealpart;", +            characters: "\u{211c}", +        }); +    } + +    if first_char == 'r' && try_read("ppolint;") { +        return Some(CharRef { +            name: "ppolint;", +            characters: "\u{2a12}", +        }); +    } + +    if first_char == 'r' && try_read("triltri;") { +        return Some(CharRef { +            name: "triltri;", +            characters: "\u{29ce}", +        }); +    } + +    if first_char == 's' && try_read("cpolint;") { +        return Some(CharRef { +            name: "cpolint;", +            characters: "\u{2a13}", +        }); +    } + +    if first_char == 's' && try_read("etminus;") { +        return Some(CharRef { +            name: "etminus;", +            characters: "\u{2216}", +        }); +    } + +    if first_char == 's' && try_read("hortmid;") { +        return Some(CharRef { +            name: "hortmid;", +            characters: "\u{2223}", +        }); +    } + +    if first_char == 's' && try_read("meparsl;") { +        return Some(CharRef { +            name: "meparsl;", +            characters: "\u{29e4}", +        }); +    } + +    if first_char == 's' && try_read("qsubset;") { +        return Some(CharRef { +            name: "qsubset;", +            characters: "\u{228f}", +        }); +    } + +    if first_char == 's' && try_read("qsupset;") { +        return Some(CharRef { +            name: "qsupset;", +            characters: "\u{2290}", +        }); +    } + +    if first_char == 's' && try_read("ubseteq;") { +        return Some(CharRef { +            name: "ubseteq;", +            characters: "\u{2286}", +        }); +    } + +    if first_char == 's' && try_read("uccneqq;") { +        return Some(CharRef { +            name: "uccneqq;", +            characters: "\u{2ab6}", +        }); +    } + +    if first_char == 's' && try_read("uccnsim;") { +        return Some(CharRef { +            name: "uccnsim;", +            characters: "\u{22e9}", +        }); +    } + +    if first_char == 's' && try_read("upseteq;") { +        return Some(CharRef { +            name: "upseteq;", +            characters: "\u{2287}", +        }); +    } + +    if first_char == 't' && try_read("hetasym;") { +        return Some(CharRef { +            name: "hetasym;", +            characters: "\u{3d1}", +        }); +    } + +    if first_char == 't' && try_read("hicksim;") { +        return Some(CharRef { +            name: "hicksim;", +            characters: "\u{223c}", +        }); +    } + +    if first_char == 't' && try_read("imesbar;") { +        return Some(CharRef { +            name: "imesbar;", +            characters: "\u{2a31}", +        }); +    } + +    if first_char == 't' && try_read("riangle;") { +        return Some(CharRef { +            name: "riangle;", +            characters: "\u{25b5}", +        }); +    } + +    if first_char == 't' && try_read("riminus;") { +        return Some(CharRef { +            name: "riminus;", +            characters: "\u{2a3a}", +        }); +    } + +    if first_char == 't' && try_read("rpezium;") { +        return Some(CharRef { +            name: "rpezium;", +            characters: "\u{23e2}", +        }); +    } + +    if first_char == 'u' && try_read("lcorner;") { +        return Some(CharRef { +            name: "lcorner;", +            characters: "\u{231c}", +        }); +    } + +    if first_char == 'u' && try_read("rcorner;") { +        return Some(CharRef { +            name: "rcorner;", +            characters: "\u{231d}", +        }); +    } + +    if first_char == 'v' && try_read("arkappa;") { +        return Some(CharRef { +            name: "arkappa;", +            characters: "\u{3f0}", +        }); +    } + +    if first_char == 'v' && try_read("arsigma;") { +        return Some(CharRef { +            name: "arsigma;", +            characters: "\u{3c2}", +        }); +    } + +    if first_char == 'v' && try_read("artheta;") { +        return Some(CharRef { +            name: "artheta;", +            characters: "\u{3d1}", +        }); +    } + +    if first_char == 'B' && try_read("ecause;") { +        return Some(CharRef { +            name: "ecause;", +            characters: "\u{2235}", +        }); +    } + +    if first_char == 'C' && try_read("ayleys;") { +        return Some(CharRef { +            name: "ayleys;", +            characters: "\u{212d}", +        }); +    } + +    if first_char == 'C' && try_read("conint;") { +        return Some(CharRef { +            name: "conint;", +            characters: "\u{2230}", +        }); +    } + +    if first_char == 'C' && try_read("edilla;") { +        return Some(CharRef { +            name: "edilla;", +            characters: "\u{b8}", +        }); +    } + +    if first_char == 'D' && try_read("iamond;") { +        return Some(CharRef { +            name: "iamond;", +            characters: "\u{22c4}", +        }); +    } + +    if first_char == 'D' && try_read("ownTee;") { +        return Some(CharRef { +            name: "ownTee;", +            characters: "\u{22a4}", +        }); +    } + +    if first_char == 'E' && try_read("lement;") { +        return Some(CharRef { +            name: "lement;", +            characters: "\u{2208}", +        }); +    } + +    if first_char == 'E' && try_read("psilon;") { +        return Some(CharRef { +            name: "psilon;", +            characters: "\u{395}", +        }); +    } + +    if first_char == 'I' && try_read("mplies;") { +        return Some(CharRef { +            name: "mplies;", +            characters: "\u{21d2}", +        }); +    } + +    if first_char == 'L' && try_read("eftTee;") { +        return Some(CharRef { +            name: "eftTee;", +            characters: "\u{22a3}", +        }); +    } + +    if first_char == 'N' && try_read("ewLine;") { +        return Some(CharRef { +            name: "ewLine;", +            characters: "\u{a}", +        }); +    } + +    if first_char == 'N' && try_read("oBreak;") { +        return Some(CharRef { +            name: "oBreak;", +            characters: "\u{2060}", +        }); +    } + +    if first_char == 'N' && try_read("otLess;") { +        return Some(CharRef { +            name: "otLess;", +            characters: "\u{226e}", +        }); +    } + +    if first_char == 'O' && try_read("micron;") { +        return Some(CharRef { +            name: "micron;", +            characters: "\u{39f}", +        }); +    } + +    if first_char == 'O' && try_read("verBar;") { +        return Some(CharRef { +            name: "verBar;", +            characters: "\u{203e}", +        }); +    } + +    if first_char == 'P' && try_read("roduct;") { +        return Some(CharRef { +            name: "roduct;", +            characters: "\u{220f}", +        }); +    } + +    if first_char == 'U' && try_read("pArrow;") { +        return Some(CharRef { +            name: "pArrow;", +            characters: "\u{2191}", +        }); +    } + +    if first_char == 'U' && try_read("parrow;") { +        return Some(CharRef { +            name: "parrow;", +            characters: "\u{21d1}", +        }); +    } + +    if first_char == 'U' && try_read("psilon;") { +        return Some(CharRef { +            name: "psilon;", +            characters: "\u{3a5}", +        }); +    } + +    if first_char == 'a' && try_read("lefsym;") { +        return Some(CharRef { +            name: "lefsym;", +            characters: "\u{2135}", +        }); +    } + +    if first_char == 'a' && try_read("ngrtvb;") { +        return Some(CharRef { +            name: "ngrtvb;", +            characters: "\u{22be}", +        }); +    } + +    if first_char == 'a' && try_read("ngzarr;") { +        return Some(CharRef { +            name: "ngzarr;", +            characters: "\u{237c}", +        }); +    } + +    if first_char == 'a' && try_read("sympeq;") { +        return Some(CharRef { +            name: "sympeq;", +            characters: "\u{224d}", +        }); +    } + +    if first_char == 'b' && try_read("acksim;") { +        return Some(CharRef { +            name: "acksim;", +            characters: "\u{223d}", +        }); +    } + +    if first_char == 'b' && try_read("ecause;") { +        return Some(CharRef { +            name: "ecause;", +            characters: "\u{2235}", +        }); +    } + +    if first_char == 'b' && try_read("emptyv;") { +        return Some(CharRef { +            name: "emptyv;", +            characters: "\u{29b0}", +        }); +    } + +    if first_char == 'b' && try_read("etween;") { +        return Some(CharRef { +            name: "etween;", +            characters: "\u{226c}", +        }); +    } + +    if first_char == 'b' && try_read("igcirc;") { +        return Some(CharRef { +            name: "igcirc;", +            characters: "\u{25ef}", +        }); +    } + +    if first_char == 'b' && try_read("igodot;") { +        return Some(CharRef { +            name: "igodot;", +            characters: "\u{2a00}", +        }); +    } + +    if first_char == 'b' && try_read("igstar;") { +        return Some(CharRef { +            name: "igstar;", +            characters: "\u{2605}", +        }); +    } + +    if first_char == 'b' && try_read("nequiv;") { +        return Some(CharRef { +            name: "nequiv;", +            characters: "\u{2261}\u{20e5}", +        }); +    } + +    if first_char == 'b' && try_read("oxplus;") { +        return Some(CharRef { +            name: "oxplus;", +            characters: "\u{229e}", +        }); +    } + +    if first_char == 'c' && try_read("cupssm;") { +        return Some(CharRef { +            name: "cupssm;", +            characters: "\u{2a50}", +        }); +    } + +    if first_char == 'c' && try_read("emptyv;") { +        return Some(CharRef { +            name: "emptyv;", +            characters: "\u{29b2}", +        }); +    } + +    if first_char == 'c' && try_read("irscir;") { +        return Some(CharRef { +            name: "irscir;", +            characters: "\u{29c2}", +        }); +    } + +    if first_char == 'c' && try_read("oloneq;") { +        return Some(CharRef { +            name: "oloneq;", +            characters: "\u{2254}", +        }); +    } + +    if first_char == 'c' && try_read("ongdot;") { +        return Some(CharRef { +            name: "ongdot;", +            characters: "\u{2a6d}", +        }); +    } + +    if first_char == 'c' && try_read("udarrl;") { +        return Some(CharRef { +            name: "udarrl;", +            characters: "\u{2938}", +        }); +    } + +    if first_char == 'c' && try_read("udarrr;") { +        return Some(CharRef { +            name: "udarrr;", +            characters: "\u{2935}", +        }); +    } + +    if first_char == 'c' && try_read("ularrp;") { +        return Some(CharRef { +            name: "ularrp;", +            characters: "\u{293d}", +        }); +    } + +    if first_char == 'c' && try_read("urarrm;") { +        return Some(CharRef { +            name: "urarrm;", +            characters: "\u{293c}", +        }); +    } + +    if first_char == 'd' && try_read("bkarow;") { +        return Some(CharRef { +            name: "bkarow;", +            characters: "\u{290f}", +        }); +    } + +    if first_char == 'd' && try_read("dagger;") { +        return Some(CharRef { +            name: "dagger;", +            characters: "\u{2021}", +        }); +    } + +    if first_char == 'd' && try_read("dotseq;") { +        return Some(CharRef { +            name: "dotseq;", +            characters: "\u{2a77}", +        }); +    } + +    if first_char == 'd' && try_read("emptyv;") { +        return Some(CharRef { +            name: "emptyv;", +            characters: "\u{29b1}", +        }); +    } + +    if first_char == 'd' && try_read("iamond;") { +        return Some(CharRef { +            name: "iamond;", +            characters: "\u{22c4}", +        }); +    } + +    if first_char == 'd' && try_read("igamma;") { +        return Some(CharRef { +            name: "igamma;", +            characters: "\u{3dd}", +        }); +    } + +    if first_char == 'd' && try_read("otplus;") { +        return Some(CharRef { +            name: "otplus;", +            characters: "\u{2214}", +        }); +    } + +    if first_char == 'd' && try_read("wangle;") { +        return Some(CharRef { +            name: "wangle;", +            characters: "\u{29a6}", +        }); +    } + +    if first_char == 'e' && try_read("psilon;") { +        return Some(CharRef { +            name: "psilon;", +            characters: "\u{3b5}", +        }); +    } + +    if first_char == 'e' && try_read("qcolon;") { +        return Some(CharRef { +            name: "qcolon;", +            characters: "\u{2255}", +        }); +    } + +    if first_char == 'e' && try_read("quivDD;") { +        return Some(CharRef { +            name: "quivDD;", +            characters: "\u{2a78}", +        }); +    } + +    if first_char == 'g' && try_read("esdoto;") { +        return Some(CharRef { +            name: "esdoto;", +            characters: "\u{2a82}", +        }); +    } + +    if first_char == 'g' && try_read("tquest;") { +        return Some(CharRef { +            name: "tquest;", +            characters: "\u{2a7c}", +        }); +    } + +    if first_char == 'g' && try_read("trless;") { +        return Some(CharRef { +            name: "trless;", +            characters: "\u{2277}", +        }); +    } + +    if first_char == 'h' && try_read("arrcir;") { +        return Some(CharRef { +            name: "arrcir;", +            characters: "\u{2948}", +        }); +    } + +    if first_char == 'i' && try_read("ntprod;") { +        return Some(CharRef { +            name: "ntprod;", +            characters: "\u{2a3c}", +        }); +    } + +    if first_char == 'i' && try_read("sindot;") { +        return Some(CharRef { +            name: "sindot;", +            characters: "\u{22f5}", +        }); +    } + +    if first_char == 'l' && try_read("arrbfs;") { +        return Some(CharRef { +            name: "arrbfs;", +            characters: "\u{291f}", +        }); +    } + +    if first_char == 'l' && try_read("arrsim;") { +        return Some(CharRef { +            name: "arrsim;", +            characters: "\u{2973}", +        }); +    } + +    if first_char == 'l' && try_read("brksld;") { +        return Some(CharRef { +            name: "brksld;", +            characters: "\u{298f}", +        }); +    } + +    if first_char == 'l' && try_read("brkslu;") { +        return Some(CharRef { +            name: "brkslu;", +            characters: "\u{298d}", +        }); +    } + +    if first_char == 'l' && try_read("drdhar;") { +        return Some(CharRef { +            name: "drdhar;", +            characters: "\u{2967}", +        }); +    } + +    if first_char == 'l' && try_read("esdoto;") { +        return Some(CharRef { +            name: "esdoto;", +            characters: "\u{2a81}", +        }); +    } + +    if first_char == 'l' && try_read("essdot;") { +        return Some(CharRef { +            name: "essdot;", +            characters: "\u{22d6}", +        }); +    } + +    if first_char == 'l' && try_read("essgtr;") { +        return Some(CharRef { +            name: "essgtr;", +            characters: "\u{2276}", +        }); +    } + +    if first_char == 'l' && try_read("esssim;") { +        return Some(CharRef { +            name: "esssim;", +            characters: "\u{2272}", +        }); +    } + +    if first_char == 'l' && try_read("otimes;") { +        return Some(CharRef { +            name: "otimes;", +            characters: "\u{2a34}", +        }); +    } + +    if first_char == 'l' && try_read("ozenge;") { +        return Some(CharRef { +            name: "ozenge;", +            characters: "\u{25ca}", +        }); +    } + +    if first_char == 'l' && try_read("tquest;") { +        return Some(CharRef { +            name: "tquest;", +            characters: "\u{2a7b}", +        }); +    } + +    if first_char == 'l' && try_read("uruhar;") { +        return Some(CharRef { +            name: "uruhar;", +            characters: "\u{2966}", +        }); +    } + +    if first_char == 'm' && try_read("altese;") { +        return Some(CharRef { +            name: "altese;", +            characters: "\u{2720}", +        }); +    } + +    if first_char == 'm' && try_read("inusdu;") { +        return Some(CharRef { +            name: "inusdu;", +            characters: "\u{2a2a}", +        }); +    } + +    if first_char == 'n' && try_read("approx;") { +        return Some(CharRef { +            name: "approx;", +            characters: "\u{2249}", +        }); +    } + +    if first_char == 'n' && try_read("atural;") { +        return Some(CharRef { +            name: "atural;", +            characters: "\u{266e}", +        }); +    } + +    if first_char == 'n' && try_read("earrow;") { +        return Some(CharRef { +            name: "earrow;", +            characters: "\u{2197}", +        }); +    } + +    if first_char == 'n' && try_read("exists;") { +        return Some(CharRef { +            name: "exists;", +            characters: "\u{2204}", +        }); +    } + +    if first_char == 'n' && try_read("otinva;") { +        return Some(CharRef { +            name: "otinva;", +            characters: "\u{2209}", +        }); +    } + +    if first_char == 'n' && try_read("otinvb;") { +        return Some(CharRef { +            name: "otinvb;", +            characters: "\u{22f7}", +        }); +    } + +    if first_char == 'n' && try_read("otinvc;") { +        return Some(CharRef { +            name: "otinvc;", +            characters: "\u{22f6}", +        }); +    } + +    if first_char == 'n' && try_read("otniva;") { +        return Some(CharRef { +            name: "otniva;", +            characters: "\u{220c}", +        }); +    } + +    if first_char == 'n' && try_read("otnivb;") { +        return Some(CharRef { +            name: "otnivb;", +            characters: "\u{22fe}", +        }); +    } + +    if first_char == 'n' && try_read("otnivc;") { +        return Some(CharRef { +            name: "otnivc;", +            characters: "\u{22fd}", +        }); +    } + +    if first_char == 'n' && try_read("polint;") { +        return Some(CharRef { +            name: "polint;", +            characters: "\u{2a14}", +        }); +    } + +    if first_char == 'n' && try_read("preceq;") { +        return Some(CharRef { +            name: "preceq;", +            characters: "\u{2aaf}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("sqsube;") { +        return Some(CharRef { +            name: "sqsube;", +            characters: "\u{22e2}", +        }); +    } + +    if first_char == 'n' && try_read("sqsupe;") { +        return Some(CharRef { +            name: "sqsupe;", +            characters: "\u{22e3}", +        }); +    } + +    if first_char == 'n' && try_read("subset;") { +        return Some(CharRef { +            name: "subset;", +            characters: "\u{2282}\u{20d2}", +        }); +    } + +    if first_char == 'n' && try_read("succeq;") { +        return Some(CharRef { +            name: "succeq;", +            characters: "\u{2ab0}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("supset;") { +        return Some(CharRef { +            name: "supset;", +            characters: "\u{2283}\u{20d2}", +        }); +    } + +    if first_char == 'n' && try_read("vinfin;") { +        return Some(CharRef { +            name: "vinfin;", +            characters: "\u{29de}", +        }); +    } + +    if first_char == 'n' && try_read("vltrie;") { +        return Some(CharRef { +            name: "vltrie;", +            characters: "\u{22b4}\u{20d2}", +        }); +    } + +    if first_char == 'n' && try_read("vrtrie;") { +        return Some(CharRef { +            name: "vrtrie;", +            characters: "\u{22b5}\u{20d2}", +        }); +    } + +    if first_char == 'n' && try_read("warrow;") { +        return Some(CharRef { +            name: "warrow;", +            characters: "\u{2196}", +        }); +    } + +    if first_char == 'o' && try_read("lcross;") { +        return Some(CharRef { +            name: "lcross;", +            characters: "\u{29bb}", +        }); +    } + +    if first_char == 'o' && try_read("micron;") { +        return Some(CharRef { +            name: "micron;", +            characters: "\u{3bf}", +        }); +    } + +    if first_char == 'o' && try_read("rderof;") { +        return Some(CharRef { +            name: "rderof;", +            characters: "\u{2134}", +        }); +    } + +    if first_char == 'o' && try_read("rslope;") { +        return Some(CharRef { +            name: "rslope;", +            characters: "\u{2a57}", +        }); +    } + +    if first_char == 'p' && try_read("ertenk;") { +        return Some(CharRef { +            name: "ertenk;", +            characters: "\u{2031}", +        }); +    } + +    if first_char == 'p' && try_read("lanckh;") { +        return Some(CharRef { +            name: "lanckh;", +            characters: "\u{210e}", +        }); +    } + +    if first_char == 'p' && try_read("luscir;") { +        return Some(CharRef { +            name: "luscir;", +            characters: "\u{2a22}", +        }); +    } + +    if first_char == 'p' && try_read("lussim;") { +        return Some(CharRef { +            name: "lussim;", +            characters: "\u{2a26}", +        }); +    } + +    if first_char == 'p' && try_read("lustwo;") { +        return Some(CharRef { +            name: "lustwo;", +            characters: "\u{2a27}", +        }); +    } + +    if first_char == 'p' && try_read("recsim;") { +        return Some(CharRef { +            name: "recsim;", +            characters: "\u{227e}", +        }); +    } + +    if first_char == 'q' && try_read("uatint;") { +        return Some(CharRef { +            name: "uatint;", +            characters: "\u{2a16}", +        }); +    } + +    if first_char == 'q' && try_read("uesteq;") { +        return Some(CharRef { +            name: "uesteq;", +            characters: "\u{225f}", +        }); +    } + +    if first_char == 'r' && try_read("arrbfs;") { +        return Some(CharRef { +            name: "arrbfs;", +            characters: "\u{2920}", +        }); +    } + +    if first_char == 'r' && try_read("arrsim;") { +        return Some(CharRef { +            name: "arrsim;", +            characters: "\u{2974}", +        }); +    } + +    if first_char == 'r' && try_read("brksld;") { +        return Some(CharRef { +            name: "brksld;", +            characters: "\u{298e}", +        }); +    } + +    if first_char == 'r' && try_read("brkslu;") { +        return Some(CharRef { +            name: "brkslu;", +            characters: "\u{2990}", +        }); +    } + +    if first_char == 'r' && try_read("dldhar;") { +        return Some(CharRef { +            name: "dldhar;", +            characters: "\u{2969}", +        }); +    } + +    if first_char == 'r' && try_read("ealine;") { +        return Some(CharRef { +            name: "ealine;", +            characters: "\u{211b}", +        }); +    } + +    if first_char == 'r' && try_read("otimes;") { +        return Some(CharRef { +            name: "otimes;", +            characters: "\u{2a35}", +        }); +    } + +    if first_char == 'r' && try_read("uluhar;") { +        return Some(CharRef { +            name: "uluhar;", +            characters: "\u{2968}", +        }); +    } + +    if first_char == 's' && try_read("earrow;") { +        return Some(CharRef { +            name: "earrow;", +            characters: "\u{2198}", +        }); +    } + +    if first_char == 's' && try_read("implus;") { +        return Some(CharRef { +            name: "implus;", +            characters: "\u{2a24}", +        }); +    } + +    if first_char == 's' && try_read("imrarr;") { +        return Some(CharRef { +            name: "imrarr;", +            characters: "\u{2972}", +        }); +    } + +    if first_char == 's' && try_read("ubedot;") { +        return Some(CharRef { +            name: "ubedot;", +            characters: "\u{2ac3}", +        }); +    } + +    if first_char == 's' && try_read("ubmult;") { +        return Some(CharRef { +            name: "ubmult;", +            characters: "\u{2ac1}", +        }); +    } + +    if first_char == 's' && try_read("ubplus;") { +        return Some(CharRef { +            name: "ubplus;", +            characters: "\u{2abf}", +        }); +    } + +    if first_char == 's' && try_read("ubrarr;") { +        return Some(CharRef { +            name: "ubrarr;", +            characters: "\u{2979}", +        }); +    } + +    if first_char == 's' && try_read("uccsim;") { +        return Some(CharRef { +            name: "uccsim;", +            characters: "\u{227f}", +        }); +    } + +    if first_char == 's' && try_read("updsub;") { +        return Some(CharRef { +            name: "updsub;", +            characters: "\u{2ad8}", +        }); +    } + +    if first_char == 's' && try_read("upedot;") { +        return Some(CharRef { +            name: "upedot;", +            characters: "\u{2ac4}", +        }); +    } + +    if first_char == 's' && try_read("uphsol;") { +        return Some(CharRef { +            name: "uphsol;", +            characters: "\u{27c9}", +        }); +    } + +    if first_char == 's' && try_read("uphsub;") { +        return Some(CharRef { +            name: "uphsub;", +            characters: "\u{2ad7}", +        }); +    } + +    if first_char == 's' && try_read("uplarr;") { +        return Some(CharRef { +            name: "uplarr;", +            characters: "\u{297b}", +        }); +    } + +    if first_char == 's' && try_read("upmult;") { +        return Some(CharRef { +            name: "upmult;", +            characters: "\u{2ac2}", +        }); +    } + +    if first_char == 's' && try_read("upplus;") { +        return Some(CharRef { +            name: "upplus;", +            characters: "\u{2ac0}", +        }); +    } + +    if first_char == 's' && try_read("warrow;") { +        return Some(CharRef { +            name: "warrow;", +            characters: "\u{2199}", +        }); +    } + +    if first_char == 't' && try_read("opfork;") { +        return Some(CharRef { +            name: "opfork;", +            characters: "\u{2ada}", +        }); +    } + +    if first_char == 't' && try_read("riplus;") { +        return Some(CharRef { +            name: "riplus;", +            characters: "\u{2a39}", +        }); +    } + +    if first_char == 't' && try_read("ritime;") { +        return Some(CharRef { +            name: "ritime;", +            characters: "\u{2a3b}", +        }); +    } + +    if first_char == 'u' && try_read("parrow;") { +        return Some(CharRef { +            name: "parrow;", +            characters: "\u{2191}", +        }); +    } + +    if first_char == 'u' && try_read("psilon;") { +        return Some(CharRef { +            name: "psilon;", +            characters: "\u{3c5}", +        }); +    } + +    if first_char == 'u' && try_read("wangle;") { +        return Some(CharRef { +            name: "wangle;", +            characters: "\u{29a7}", +        }); +    } + +    if first_char == 'v' && try_read("zigzag;") { +        return Some(CharRef { +            name: "zigzag;", +            characters: "\u{299a}", +        }); +    } + +    if first_char == 'z' && try_read("igrarr;") { +        return Some(CharRef { +            name: "igrarr;", +            characters: "\u{21dd}", +        }); +    } + +    if first_char == 'A' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{c1}", +        }); +    } + +    if first_char == 'A' && try_read("breve;") { +        return Some(CharRef { +            name: "breve;", +            characters: "\u{102}", +        }); +    } + +    if first_char == 'A' && try_read("grave;") { +        return Some(CharRef { +            name: "grave;", +            characters: "\u{c0}", +        }); +    } + +    if first_char == 'A' && try_read("ssign;") { +        return Some(CharRef { +            name: "ssign;", +            characters: "\u{2254}", +        }); +    } + +    if first_char == 'A' && try_read("tilde;") { +        return Some(CharRef { +            name: "tilde;", +            characters: "\u{c3}", +        }); +    } + +    if first_char == 'B' && try_read("arwed;") { +        return Some(CharRef { +            name: "arwed;", +            characters: "\u{2306}", +        }); +    } + +    if first_char == 'B' && try_read("umpeq;") { +        return Some(CharRef { +            name: "umpeq;", +            characters: "\u{224e}", +        }); +    } + +    if first_char == 'C' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{106}", +        }); +    } + +    if first_char == 'C' && try_read("caron;") { +        return Some(CharRef { +            name: "caron;", +            characters: "\u{10c}", +        }); +    } + +    if first_char == 'C' && try_read("cedil;") { +        return Some(CharRef { +            name: "cedil;", +            characters: "\u{c7}", +        }); +    } + +    if first_char == 'C' && try_read("olone;") { +        return Some(CharRef { +            name: "olone;", +            characters: "\u{2a74}", +        }); +    } + +    if first_char == 'C' && try_read("onint;") { +        return Some(CharRef { +            name: "onint;", +            characters: "\u{222f}", +        }); +    } + +    if first_char == 'C' && try_read("upCap;") { +        return Some(CharRef { +            name: "upCap;", +            characters: "\u{224d}", +        }); +    } + +    if first_char == 'D' && try_read("agger;") { +        return Some(CharRef { +            name: "agger;", +            characters: "\u{2021}", +        }); +    } + +    if first_char == 'D' && try_read("caron;") { +        return Some(CharRef { +            name: "caron;", +            characters: "\u{10e}", +        }); +    } + +    if first_char == 'D' && try_read("otDot;") { +        return Some(CharRef { +            name: "otDot;", +            characters: "\u{20dc}", +        }); +    } + +    if first_char == 'D' && try_read("strok;") { +        return Some(CharRef { +            name: "strok;", +            characters: "\u{110}", +        }); +    } + +    if first_char == 'E' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{c9}", +        }); +    } + +    if first_char == 'E' && try_read("caron;") { +        return Some(CharRef { +            name: "caron;", +            characters: "\u{11a}", +        }); +    } + +    if first_char == 'E' && try_read("grave;") { +        return Some(CharRef { +            name: "grave;", +            characters: "\u{c8}", +        }); +    } + +    if first_char == 'E' && try_read("xists;") { +        return Some(CharRef { +            name: "xists;", +            characters: "\u{2203}", +        }); +    } + +    if first_char == 'F' && try_read("orAll;") { +        return Some(CharRef { +            name: "orAll;", +            characters: "\u{2200}", +        }); +    } + +    if first_char == 'G' && try_read("ammad;") { +        return Some(CharRef { +            name: "ammad;", +            characters: "\u{3dc}", +        }); +    } + +    if first_char == 'G' && try_read("breve;") { +        return Some(CharRef { +            name: "breve;", +            characters: "\u{11e}", +        }); +    } + +    if first_char == 'G' && try_read("cedil;") { +        return Some(CharRef { +            name: "cedil;", +            characters: "\u{122}", +        }); +    } + +    if first_char == 'H' && try_read("ARDcy;") { +        return Some(CharRef { +            name: "ARDcy;", +            characters: "\u{42a}", +        }); +    } + +    if first_char == 'H' && try_read("strok;") { +        return Some(CharRef { +            name: "strok;", +            characters: "\u{126}", +        }); +    } + +    if first_char == 'I' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{cd}", +        }); +    } + +    if first_char == 'I' && try_read("grave;") { +        return Some(CharRef { +            name: "grave;", +            characters: "\u{cc}", +        }); +    } + +    if first_char == 'I' && try_read("tilde;") { +        return Some(CharRef { +            name: "tilde;", +            characters: "\u{128}", +        }); +    } + +    if first_char == 'J' && try_read("sercy;") { +        return Some(CharRef { +            name: "sercy;", +            characters: "\u{408}", +        }); +    } + +    if first_char == 'K' && try_read("cedil;") { +        return Some(CharRef { +            name: "cedil;", +            characters: "\u{136}", +        }); +    } + +    if first_char == 'L' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{139}", +        }); +    } + +    if first_char == 'L' && try_read("ambda;") { +        return Some(CharRef { +            name: "ambda;", +            characters: "\u{39b}", +        }); +    } + +    if first_char == 'L' && try_read("caron;") { +        return Some(CharRef { +            name: "caron;", +            characters: "\u{13d}", +        }); +    } + +    if first_char == 'L' && try_read("cedil;") { +        return Some(CharRef { +            name: "cedil;", +            characters: "\u{13b}", +        }); +    } + +    if first_char == 'L' && try_read("midot;") { +        return Some(CharRef { +            name: "midot;", +            characters: "\u{13f}", +        }); +    } + +    if first_char == 'L' && try_read("strok;") { +        return Some(CharRef { +            name: "strok;", +            characters: "\u{141}", +        }); +    } + +    if first_char == 'N' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{143}", +        }); +    } + +    if first_char == 'N' && try_read("caron;") { +        return Some(CharRef { +            name: "caron;", +            characters: "\u{147}", +        }); +    } + +    if first_char == 'N' && try_read("cedil;") { +        return Some(CharRef { +            name: "cedil;", +            characters: "\u{145}", +        }); +    } + +    if first_char == 'N' && try_read("tilde;") { +        return Some(CharRef { +            name: "tilde;", +            characters: "\u{d1}", +        }); +    } + +    if first_char == 'O' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{d3}", +        }); +    } + +    if first_char == 'O' && try_read("dblac;") { +        return Some(CharRef { +            name: "dblac;", +            characters: "\u{150}", +        }); +    } + +    if first_char == 'O' && try_read("grave;") { +        return Some(CharRef { +            name: "grave;", +            characters: "\u{d2}", +        }); +    } + +    if first_char == 'O' && try_read("slash;") { +        return Some(CharRef { +            name: "slash;", +            characters: "\u{d8}", +        }); +    } + +    if first_char == 'O' && try_read("tilde;") { +        return Some(CharRef { +            name: "tilde;", +            characters: "\u{d5}", +        }); +    } + +    if first_char == 'O' && try_read("times;") { +        return Some(CharRef { +            name: "times;", +            characters: "\u{2a37}", +        }); +    } + +    if first_char == 'R' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{154}", +        }); +    } + +    if first_char == 'R' && try_read("arrtl;") { +        return Some(CharRef { +            name: "arrtl;", +            characters: "\u{2916}", +        }); +    } + +    if first_char == 'R' && try_read("caron;") { +        return Some(CharRef { +            name: "caron;", +            characters: "\u{158}", +        }); +    } + +    if first_char == 'R' && try_read("cedil;") { +        return Some(CharRef { +            name: "cedil;", +            characters: "\u{156}", +        }); +    } + +    if first_char == 'S' && try_read("HCHcy;") { +        return Some(CharRef { +            name: "HCHcy;", +            characters: "\u{429}", +        }); +    } + +    if first_char == 'S' && try_read("OFTcy;") { +        return Some(CharRef { +            name: "OFTcy;", +            characters: "\u{42c}", +        }); +    } + +    if first_char == 'S' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{15a}", +        }); +    } + +    if first_char == 'S' && try_read("caron;") { +        return Some(CharRef { +            name: "caron;", +            characters: "\u{160}", +        }); +    } + +    if first_char == 'S' && try_read("cedil;") { +        return Some(CharRef { +            name: "cedil;", +            characters: "\u{15e}", +        }); +    } + +    if first_char == 'S' && try_read("quare;") { +        return Some(CharRef { +            name: "quare;", +            characters: "\u{25a1}", +        }); +    } + +    if first_char == 'S' && try_read("ubset;") { +        return Some(CharRef { +            name: "ubset;", +            characters: "\u{22d0}", +        }); +    } + +    if first_char == 'S' && try_read("upset;") { +        return Some(CharRef { +            name: "upset;", +            characters: "\u{22d1}", +        }); +    } + +    if first_char == 'T' && try_read("caron;") { +        return Some(CharRef { +            name: "caron;", +            characters: "\u{164}", +        }); +    } + +    if first_char == 'T' && try_read("cedil;") { +        return Some(CharRef { +            name: "cedil;", +            characters: "\u{162}", +        }); +    } + +    if first_char == 'T' && try_read("strok;") { +        return Some(CharRef { +            name: "strok;", +            characters: "\u{166}", +        }); +    } + +    if first_char == 'U' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{da}", +        }); +    } + +    if first_char == 'U' && try_read("breve;") { +        return Some(CharRef { +            name: "breve;", +            characters: "\u{16c}", +        }); +    } + +    if first_char == 'U' && try_read("dblac;") { +        return Some(CharRef { +            name: "dblac;", +            characters: "\u{170}", +        }); +    } + +    if first_char == 'U' && try_read("grave;") { +        return Some(CharRef { +            name: "grave;", +            characters: "\u{d9}", +        }); +    } + +    if first_char == 'U' && try_read("tilde;") { +        return Some(CharRef { +            name: "tilde;", +            characters: "\u{168}", +        }); +    } + +    if first_char == 'V' && try_read("dashl;") { +        return Some(CharRef { +            name: "dashl;", +            characters: "\u{2ae6}", +        }); +    } + +    if first_char == 'V' && try_read("erbar;") { +        return Some(CharRef { +            name: "erbar;", +            characters: "\u{2016}", +        }); +    } + +    if first_char == 'V' && try_read("vdash;") { +        return Some(CharRef { +            name: "vdash;", +            characters: "\u{22aa}", +        }); +    } + +    if first_char == 'Y' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{dd}", +        }); +    } + +    if first_char == 'Z' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{179}", +        }); +    } + +    if first_char == 'Z' && try_read("caron;") { +        return Some(CharRef { +            name: "caron;", +            characters: "\u{17d}", +        }); +    } + +    if first_char == 'a' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{e1}", +        }); +    } + +    if first_char == 'a' && try_read("breve;") { +        return Some(CharRef { +            name: "breve;", +            characters: "\u{103}", +        }); +    } + +    if first_char == 'a' && try_read("grave;") { +        return Some(CharRef { +            name: "grave;", +            characters: "\u{e0}", +        }); +    } + +    if first_char == 'a' && try_read("ndand;") { +        return Some(CharRef { +            name: "ndand;", +            characters: "\u{2a55}", +        }); +    } + +    if first_char == 'a' && try_read("ngmsd;") { +        return Some(CharRef { +            name: "ngmsd;", +            characters: "\u{2221}", +        }); +    } + +    if first_char == 'a' && try_read("ngsph;") { +        return Some(CharRef { +            name: "ngsph;", +            characters: "\u{2222}", +        }); +    } + +    if first_char == 'a' && try_read("pacir;") { +        return Some(CharRef { +            name: "pacir;", +            characters: "\u{2a6f}", +        }); +    } + +    if first_char == 'a' && try_read("pprox;") { +        return Some(CharRef { +            name: "pprox;", +            characters: "\u{2248}", +        }); +    } + +    if first_char == 'a' && try_read("tilde;") { +        return Some(CharRef { +            name: "tilde;", +            characters: "\u{e3}", +        }); +    } + +    if first_char == 'b' && try_read("arvee;") { +        return Some(CharRef { +            name: "arvee;", +            characters: "\u{22bd}", +        }); +    } + +    if first_char == 'b' && try_read("arwed;") { +        return Some(CharRef { +            name: "arwed;", +            characters: "\u{2305}", +        }); +    } + +    if first_char == 'b' && try_read("ecaus;") { +        return Some(CharRef { +            name: "ecaus;", +            characters: "\u{2235}", +        }); +    } + +    if first_char == 'b' && try_read("ernou;") { +        return Some(CharRef { +            name: "ernou;", +            characters: "\u{212c}", +        }); +    } + +    if first_char == 'b' && try_read("igcap;") { +        return Some(CharRef { +            name: "igcap;", +            characters: "\u{22c2}", +        }); +    } + +    if first_char == 'b' && try_read("igcup;") { +        return Some(CharRef { +            name: "igcup;", +            characters: "\u{22c3}", +        }); +    } + +    if first_char == 'b' && try_read("igvee;") { +        return Some(CharRef { +            name: "igvee;", +            characters: "\u{22c1}", +        }); +    } + +    if first_char == 'b' && try_read("karow;") { +        return Some(CharRef { +            name: "karow;", +            characters: "\u{290d}", +        }); +    } + +    if first_char == 'b' && try_read("ottom;") { +        return Some(CharRef { +            name: "ottom;", +            characters: "\u{22a5}", +        }); +    } + +    if first_char == 'b' && try_read("owtie;") { +        return Some(CharRef { +            name: "owtie;", +            characters: "\u{22c8}", +        }); +    } + +    if first_char == 'b' && try_read("oxbox;") { +        return Some(CharRef { +            name: "oxbox;", +            characters: "\u{29c9}", +        }); +    } + +    if first_char == 'b' && try_read("prime;") { +        return Some(CharRef { +            name: "prime;", +            characters: "\u{2035}", +        }); +    } + +    if first_char == 'b' && try_read("rvbar;") { +        return Some(CharRef { +            name: "rvbar;", +            characters: "\u{a6}", +        }); +    } + +    if first_char == 'b' && try_read("ullet;") { +        return Some(CharRef { +            name: "ullet;", +            characters: "\u{2022}", +        }); +    } + +    if first_char == 'b' && try_read("umpeq;") { +        return Some(CharRef { +            name: "umpeq;", +            characters: "\u{224f}", +        }); +    } + +    if first_char == 'c' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{107}", +        }); +    } + +    if first_char == 'c' && try_read("apand;") { +        return Some(CharRef { +            name: "apand;", +            characters: "\u{2a44}", +        }); +    } + +    if first_char == 'c' && try_read("apcap;") { +        return Some(CharRef { +            name: "apcap;", +            characters: "\u{2a4b}", +        }); +    } + +    if first_char == 'c' && try_read("apcup;") { +        return Some(CharRef { +            name: "apcup;", +            characters: "\u{2a47}", +        }); +    } + +    if first_char == 'c' && try_read("apdot;") { +        return Some(CharRef { +            name: "apdot;", +            characters: "\u{2a40}", +        }); +    } + +    if first_char == 'c' && try_read("caron;") { +        return Some(CharRef { +            name: "caron;", +            characters: "\u{10d}", +        }); +    } + +    if first_char == 'c' && try_read("cedil;") { +        return Some(CharRef { +            name: "cedil;", +            characters: "\u{e7}", +        }); +    } + +    if first_char == 'c' && try_read("irceq;") { +        return Some(CharRef { +            name: "irceq;", +            characters: "\u{2257}", +        }); +    } + +    if first_char == 'c' && try_read("irmid;") { +        return Some(CharRef { +            name: "irmid;", +            characters: "\u{2aef}", +        }); +    } + +    if first_char == 'c' && try_read("olone;") { +        return Some(CharRef { +            name: "olone;", +            characters: "\u{2254}", +        }); +    } + +    if first_char == 'c' && try_read("ommat;") { +        return Some(CharRef { +            name: "ommat;", +            characters: "\u{40}", +        }); +    } + +    if first_char == 'c' && try_read("ompfn;") { +        return Some(CharRef { +            name: "ompfn;", +            characters: "\u{2218}", +        }); +    } + +    if first_char == 'c' && try_read("onint;") { +        return Some(CharRef { +            name: "onint;", +            characters: "\u{222e}", +        }); +    } + +    if first_char == 'c' && try_read("oprod;") { +        return Some(CharRef { +            name: "oprod;", +            characters: "\u{2210}", +        }); +    } + +    if first_char == 'c' && try_read("opysr;") { +        return Some(CharRef { +            name: "opysr;", +            characters: "\u{2117}", +        }); +    } + +    if first_char == 'c' && try_read("ularr;") { +        return Some(CharRef { +            name: "ularr;", +            characters: "\u{21b6}", +        }); +    } + +    if first_char == 'c' && try_read("upcap;") { +        return Some(CharRef { +            name: "upcap;", +            characters: "\u{2a46}", +        }); +    } + +    if first_char == 'c' && try_read("upcup;") { +        return Some(CharRef { +            name: "upcup;", +            characters: "\u{2a4a}", +        }); +    } + +    if first_char == 'c' && try_read("updot;") { +        return Some(CharRef { +            name: "updot;", +            characters: "\u{228d}", +        }); +    } + +    if first_char == 'c' && try_read("urarr;") { +        return Some(CharRef { +            name: "urarr;", +            characters: "\u{21b7}", +        }); +    } + +    if first_char == 'c' && try_read("urren;") { +        return Some(CharRef { +            name: "urren;", +            characters: "\u{a4}", +        }); +    } + +    if first_char == 'c' && try_read("ylcty;") { +        return Some(CharRef { +            name: "ylcty;", +            characters: "\u{232d}", +        }); +    } + +    if first_char == 'd' && try_read("agger;") { +        return Some(CharRef { +            name: "agger;", +            characters: "\u{2020}", +        }); +    } + +    if first_char == 'd' && try_read("aleth;") { +        return Some(CharRef { +            name: "aleth;", +            characters: "\u{2138}", +        }); +    } + +    if first_char == 'd' && try_read("caron;") { +        return Some(CharRef { +            name: "caron;", +            characters: "\u{10f}", +        }); +    } + +    if first_char == 'd' && try_read("fisht;") { +        return Some(CharRef { +            name: "fisht;", +            characters: "\u{297f}", +        }); +    } + +    if first_char == 'd' && try_read("ivide;") { +        return Some(CharRef { +            name: "ivide;", +            characters: "\u{f7}", +        }); +    } + +    if first_char == 'd' && try_read("ivonx;") { +        return Some(CharRef { +            name: "ivonx;", +            characters: "\u{22c7}", +        }); +    } + +    if first_char == 'd' && try_read("lcorn;") { +        return Some(CharRef { +            name: "lcorn;", +            characters: "\u{231e}", +        }); +    } + +    if first_char == 'd' && try_read("lcrop;") { +        return Some(CharRef { +            name: "lcrop;", +            characters: "\u{230d}", +        }); +    } + +    if first_char == 'd' && try_read("ollar;") { +        return Some(CharRef { +            name: "ollar;", +            characters: "\u{24}", +        }); +    } + +    if first_char == 'd' && try_read("rcorn;") { +        return Some(CharRef { +            name: "rcorn;", +            characters: "\u{231f}", +        }); +    } + +    if first_char == 'd' && try_read("rcrop;") { +        return Some(CharRef { +            name: "rcrop;", +            characters: "\u{230c}", +        }); +    } + +    if first_char == 'd' && try_read("strok;") { +        return Some(CharRef { +            name: "strok;", +            characters: "\u{111}", +        }); +    } + +    if first_char == 'e' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{e9}", +        }); +    } + +    if first_char == 'e' && try_read("aster;") { +        return Some(CharRef { +            name: "aster;", +            characters: "\u{2a6e}", +        }); +    } + +    if first_char == 'e' && try_read("caron;") { +        return Some(CharRef { +            name: "caron;", +            characters: "\u{11b}", +        }); +    } + +    if first_char == 'e' && try_read("colon;") { +        return Some(CharRef { +            name: "colon;", +            characters: "\u{2255}", +        }); +    } + +    if first_char == 'e' && try_read("grave;") { +        return Some(CharRef { +            name: "grave;", +            characters: "\u{e8}", +        }); +    } + +    if first_char == 'e' && try_read("gsdot;") { +        return Some(CharRef { +            name: "gsdot;", +            characters: "\u{2a98}", +        }); +    } + +    if first_char == 'e' && try_read("lsdot;") { +        return Some(CharRef { +            name: "lsdot;", +            characters: "\u{2a97}", +        }); +    } + +    if first_char == 'e' && try_read("mptyv;") { +        return Some(CharRef { +            name: "mptyv;", +            characters: "\u{2205}", +        }); +    } + +    if first_char == 'e' && try_read("msp13;") { +        return Some(CharRef { +            name: "msp13;", +            characters: "\u{2004}", +        }); +    } + +    if first_char == 'e' && try_read("msp14;") { +        return Some(CharRef { +            name: "msp14;", +            characters: "\u{2005}", +        }); +    } + +    if first_char == 'e' && try_read("parsl;") { +        return Some(CharRef { +            name: "parsl;", +            characters: "\u{29e3}", +        }); +    } + +    if first_char == 'e' && try_read("qcirc;") { +        return Some(CharRef { +            name: "qcirc;", +            characters: "\u{2256}", +        }); +    } + +    if first_char == 'e' && try_read("quals;") { +        return Some(CharRef { +            name: "quals;", +            characters: "\u{3d}", +        }); +    } + +    if first_char == 'e' && try_read("quest;") { +        return Some(CharRef { +            name: "quest;", +            characters: "\u{225f}", +        }); +    } + +    if first_char == 'f' && try_read("emale;") { +        return Some(CharRef { +            name: "emale;", +            characters: "\u{2640}", +        }); +    } + +    if first_char == 'f' && try_read("filig;") { +        return Some(CharRef { +            name: "filig;", +            characters: "\u{fb03}", +        }); +    } + +    if first_char == 'f' && try_read("fllig;") { +        return Some(CharRef { +            name: "fllig;", +            characters: "\u{fb04}", +        }); +    } + +    if first_char == 'f' && try_read("orall;") { +        return Some(CharRef { +            name: "orall;", +            characters: "\u{2200}", +        }); +    } + +    if first_char == 'f' && try_read("rac12;") { +        return Some(CharRef { +            name: "rac12;", +            characters: "\u{bd}", +        }); +    } + +    if first_char == 'f' && try_read("rac13;") { +        return Some(CharRef { +            name: "rac13;", +            characters: "\u{2153}", +        }); +    } + +    if first_char == 'f' && try_read("rac14;") { +        return Some(CharRef { +            name: "rac14;", +            characters: "\u{bc}", +        }); +    } + +    if first_char == 'f' && try_read("rac15;") { +        return Some(CharRef { +            name: "rac15;", +            characters: "\u{2155}", +        }); +    } + +    if first_char == 'f' && try_read("rac16;") { +        return Some(CharRef { +            name: "rac16;", +            characters: "\u{2159}", +        }); +    } + +    if first_char == 'f' && try_read("rac18;") { +        return Some(CharRef { +            name: "rac18;", +            characters: "\u{215b}", +        }); +    } + +    if first_char == 'f' && try_read("rac23;") { +        return Some(CharRef { +            name: "rac23;", +            characters: "\u{2154}", +        }); +    } + +    if first_char == 'f' && try_read("rac25;") { +        return Some(CharRef { +            name: "rac25;", +            characters: "\u{2156}", +        }); +    } + +    if first_char == 'f' && try_read("rac34;") { +        return Some(CharRef { +            name: "rac34;", +            characters: "\u{be}", +        }); +    } + +    if first_char == 'f' && try_read("rac35;") { +        return Some(CharRef { +            name: "rac35;", +            characters: "\u{2157}", +        }); +    } + +    if first_char == 'f' && try_read("rac38;") { +        return Some(CharRef { +            name: "rac38;", +            characters: "\u{215c}", +        }); +    } + +    if first_char == 'f' && try_read("rac45;") { +        return Some(CharRef { +            name: "rac45;", +            characters: "\u{2158}", +        }); +    } + +    if first_char == 'f' && try_read("rac56;") { +        return Some(CharRef { +            name: "rac56;", +            characters: "\u{215a}", +        }); +    } + +    if first_char == 'f' && try_read("rac58;") { +        return Some(CharRef { +            name: "rac58;", +            characters: "\u{215d}", +        }); +    } + +    if first_char == 'f' && try_read("rac78;") { +        return Some(CharRef { +            name: "rac78;", +            characters: "\u{215e}", +        }); +    } + +    if first_char == 'g' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{1f5}", +        }); +    } + +    if first_char == 'g' && try_read("ammad;") { +        return Some(CharRef { +            name: "ammad;", +            characters: "\u{3dd}", +        }); +    } + +    if first_char == 'g' && try_read("breve;") { +        return Some(CharRef { +            name: "breve;", +            characters: "\u{11f}", +        }); +    } + +    if first_char == 'g' && try_read("esdot;") { +        return Some(CharRef { +            name: "esdot;", +            characters: "\u{2a80}", +        }); +    } + +    if first_char == 'g' && try_read("esles;") { +        return Some(CharRef { +            name: "esles;", +            characters: "\u{2a94}", +        }); +    } + +    if first_char == 'g' && try_read("tlPar;") { +        return Some(CharRef { +            name: "tlPar;", +            characters: "\u{2995}", +        }); +    } + +    if first_char == 'g' && try_read("trarr;") { +        return Some(CharRef { +            name: "trarr;", +            characters: "\u{2978}", +        }); +    } + +    if first_char == 'g' && try_read("trdot;") { +        return Some(CharRef { +            name: "trdot;", +            characters: "\u{22d7}", +        }); +    } + +    if first_char == 'g' && try_read("trsim;") { +        return Some(CharRef { +            name: "trsim;", +            characters: "\u{2273}", +        }); +    } + +    if first_char == 'h' && try_read("airsp;") { +        return Some(CharRef { +            name: "airsp;", +            characters: "\u{200a}", +        }); +    } + +    if first_char == 'h' && try_read("amilt;") { +        return Some(CharRef { +            name: "amilt;", +            characters: "\u{210b}", +        }); +    } + +    if first_char == 'h' && try_read("ardcy;") { +        return Some(CharRef { +            name: "ardcy;", +            characters: "\u{44a}", +        }); +    } + +    if first_char == 'h' && try_read("earts;") { +        return Some(CharRef { +            name: "earts;", +            characters: "\u{2665}", +        }); +    } + +    if first_char == 'h' && try_read("ellip;") { +        return Some(CharRef { +            name: "ellip;", +            characters: "\u{2026}", +        }); +    } + +    if first_char == 'h' && try_read("ercon;") { +        return Some(CharRef { +            name: "ercon;", +            characters: "\u{22b9}", +        }); +    } + +    if first_char == 'h' && try_read("omtht;") { +        return Some(CharRef { +            name: "omtht;", +            characters: "\u{223b}", +        }); +    } + +    if first_char == 'h' && try_read("orbar;") { +        return Some(CharRef { +            name: "orbar;", +            characters: "\u{2015}", +        }); +    } + +    if first_char == 'h' && try_read("slash;") { +        return Some(CharRef { +            name: "slash;", +            characters: "\u{210f}", +        }); +    } + +    if first_char == 'h' && try_read("strok;") { +        return Some(CharRef { +            name: "strok;", +            characters: "\u{127}", +        }); +    } + +    if first_char == 'h' && try_read("ybull;") { +        return Some(CharRef { +            name: "ybull;", +            characters: "\u{2043}", +        }); +    } + +    if first_char == 'h' && try_read("yphen;") { +        return Some(CharRef { +            name: "yphen;", +            characters: "\u{2010}", +        }); +    } + +    if first_char == 'i' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{ed}", +        }); +    } + +    if first_char == 'i' && try_read("grave;") { +        return Some(CharRef { +            name: "grave;", +            characters: "\u{ec}", +        }); +    } + +    if first_char == 'i' && try_read("iiint;") { +        return Some(CharRef { +            name: "iiint;", +            characters: "\u{2a0c}", +        }); +    } + +    if first_char == 'i' && try_read("infin;") { +        return Some(CharRef { +            name: "infin;", +            characters: "\u{29dc}", +        }); +    } + +    if first_char == 'i' && try_read("ncare;") { +        return Some(CharRef { +            name: "ncare;", +            characters: "\u{2105}", +        }); +    } + +    if first_char == 'i' && try_read("nodot;") { +        return Some(CharRef { +            name: "nodot;", +            characters: "\u{131}", +        }); +    } + +    if first_char == 'i' && try_read("ntcal;") { +        return Some(CharRef { +            name: "ntcal;", +            characters: "\u{22ba}", +        }); +    } + +    if first_char == 'i' && try_read("quest;") { +        return Some(CharRef { +            name: "quest;", +            characters: "\u{bf}", +        }); +    } + +    if first_char == 'i' && try_read("sinsv;") { +        return Some(CharRef { +            name: "sinsv;", +            characters: "\u{22f3}", +        }); +    } + +    if first_char == 'i' && try_read("tilde;") { +        return Some(CharRef { +            name: "tilde;", +            characters: "\u{129}", +        }); +    } + +    if first_char == 'j' && try_read("sercy;") { +        return Some(CharRef { +            name: "sercy;", +            characters: "\u{458}", +        }); +    } + +    if first_char == 'k' && try_read("appav;") { +        return Some(CharRef { +            name: "appav;", +            characters: "\u{3f0}", +        }); +    } + +    if first_char == 'k' && try_read("cedil;") { +        return Some(CharRef { +            name: "cedil;", +            characters: "\u{137}", +        }); +    } + +    if first_char == 'k' && try_read("green;") { +        return Some(CharRef { +            name: "green;", +            characters: "\u{138}", +        }); +    } + +    if first_char == 'l' && try_read("Atail;") { +        return Some(CharRef { +            name: "Atail;", +            characters: "\u{291b}", +        }); +    } + +    if first_char == 'l' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{13a}", +        }); +    } + +    if first_char == 'l' && try_read("agran;") { +        return Some(CharRef { +            name: "agran;", +            characters: "\u{2112}", +        }); +    } + +    if first_char == 'l' && try_read("ambda;") { +        return Some(CharRef { +            name: "ambda;", +            characters: "\u{3bb}", +        }); +    } + +    if first_char == 'l' && try_read("angle;") { +        return Some(CharRef { +            name: "angle;", +            characters: "\u{27e8}", +        }); +    } + +    if first_char == 'l' && try_read("arrfs;") { +        return Some(CharRef { +            name: "arrfs;", +            characters: "\u{291d}", +        }); +    } + +    if first_char == 'l' && try_read("arrhk;") { +        return Some(CharRef { +            name: "arrhk;", +            characters: "\u{21a9}", +        }); +    } + +    if first_char == 'l' && try_read("arrlp;") { +        return Some(CharRef { +            name: "arrlp;", +            characters: "\u{21ab}", +        }); +    } + +    if first_char == 'l' && try_read("arrpl;") { +        return Some(CharRef { +            name: "arrpl;", +            characters: "\u{2939}", +        }); +    } + +    if first_char == 'l' && try_read("arrtl;") { +        return Some(CharRef { +            name: "arrtl;", +            characters: "\u{21a2}", +        }); +    } + +    if first_char == 'l' && try_read("atail;") { +        return Some(CharRef { +            name: "atail;", +            characters: "\u{2919}", +        }); +    } + +    if first_char == 'l' && try_read("brace;") { +        return Some(CharRef { +            name: "brace;", +            characters: "\u{7b}", +        }); +    } + +    if first_char == 'l' && try_read("brack;") { +        return Some(CharRef { +            name: "brack;", +            characters: "\u{5b}", +        }); +    } + +    if first_char == 'l' && try_read("caron;") { +        return Some(CharRef { +            name: "caron;", +            characters: "\u{13e}", +        }); +    } + +    if first_char == 'l' && try_read("cedil;") { +        return Some(CharRef { +            name: "cedil;", +            characters: "\u{13c}", +        }); +    } + +    if first_char == 'l' && try_read("dquor;") { +        return Some(CharRef { +            name: "dquor;", +            characters: "\u{201e}", +        }); +    } + +    if first_char == 'l' && try_read("esdot;") { +        return Some(CharRef { +            name: "esdot;", +            characters: "\u{2a7f}", +        }); +    } + +    if first_char == 'l' && try_read("esges;") { +        return Some(CharRef { +            name: "esges;", +            characters: "\u{2a93}", +        }); +    } + +    if first_char == 'l' && try_read("fisht;") { +        return Some(CharRef { +            name: "fisht;", +            characters: "\u{297c}", +        }); +    } + +    if first_char == 'l' && try_read("floor;") { +        return Some(CharRef { +            name: "floor;", +            characters: "\u{230a}", +        }); +    } + +    if first_char == 'l' && try_read("harul;") { +        return Some(CharRef { +            name: "harul;", +            characters: "\u{296a}", +        }); +    } + +    if first_char == 'l' && try_read("lhard;") { +        return Some(CharRef { +            name: "lhard;", +            characters: "\u{296b}", +        }); +    } + +    if first_char == 'l' && try_read("midot;") { +        return Some(CharRef { +            name: "midot;", +            characters: "\u{140}", +        }); +    } + +    if first_char == 'l' && try_read("moust;") { +        return Some(CharRef { +            name: "moust;", +            characters: "\u{23b0}", +        }); +    } + +    if first_char == 'l' && try_read("oplus;") { +        return Some(CharRef { +            name: "oplus;", +            characters: "\u{2a2d}", +        }); +    } + +    if first_char == 'l' && try_read("owast;") { +        return Some(CharRef { +            name: "owast;", +            characters: "\u{2217}", +        }); +    } + +    if first_char == 'l' && try_read("owbar;") { +        return Some(CharRef { +            name: "owbar;", +            characters: "\u{5f}", +        }); +    } + +    if first_char == 'l' && try_read("parlt;") { +        return Some(CharRef { +            name: "parlt;", +            characters: "\u{2993}", +        }); +    } + +    if first_char == 'l' && try_read("rhard;") { +        return Some(CharRef { +            name: "rhard;", +            characters: "\u{296d}", +        }); +    } + +    if first_char == 'l' && try_read("saquo;") { +        return Some(CharRef { +            name: "saquo;", +            characters: "\u{2039}", +        }); +    } + +    if first_char == 'l' && try_read("squor;") { +        return Some(CharRef { +            name: "squor;", +            characters: "\u{201a}", +        }); +    } + +    if first_char == 'l' && try_read("strok;") { +        return Some(CharRef { +            name: "strok;", +            characters: "\u{142}", +        }); +    } + +    if first_char == 'l' && try_read("three;") { +        return Some(CharRef { +            name: "three;", +            characters: "\u{22cb}", +        }); +    } + +    if first_char == 'l' && try_read("times;") { +        return Some(CharRef { +            name: "times;", +            characters: "\u{22c9}", +        }); +    } + +    if first_char == 'l' && try_read("tlarr;") { +        return Some(CharRef { +            name: "tlarr;", +            characters: "\u{2976}", +        }); +    } + +    if first_char == 'l' && try_read("trPar;") { +        return Some(CharRef { +            name: "trPar;", +            characters: "\u{2996}", +        }); +    } + +    if first_char == 'm' && try_read("apsto;") { +        return Some(CharRef { +            name: "apsto;", +            characters: "\u{21a6}", +        }); +    } + +    if first_char == 'm' && try_read("arker;") { +        return Some(CharRef { +            name: "arker;", +            characters: "\u{25ae}", +        }); +    } + +    if first_char == 'm' && try_read("comma;") { +        return Some(CharRef { +            name: "comma;", +            characters: "\u{2a29}", +        }); +    } + +    if first_char == 'm' && try_read("idast;") { +        return Some(CharRef { +            name: "idast;", +            characters: "\u{2a}", +        }); +    } + +    if first_char == 'm' && try_read("idcir;") { +        return Some(CharRef { +            name: "idcir;", +            characters: "\u{2af0}", +        }); +    } + +    if first_char == 'm' && try_read("iddot;") { +        return Some(CharRef { +            name: "iddot;", +            characters: "\u{b7}", +        }); +    } + +    if first_char == 'm' && try_read("inusb;") { +        return Some(CharRef { +            name: "inusb;", +            characters: "\u{229f}", +        }); +    } + +    if first_char == 'm' && try_read("inusd;") { +        return Some(CharRef { +            name: "inusd;", +            characters: "\u{2238}", +        }); +    } + +    if first_char == 'm' && try_read("nplus;") { +        return Some(CharRef { +            name: "nplus;", +            characters: "\u{2213}", +        }); +    } + +    if first_char == 'm' && try_read("odels;") { +        return Some(CharRef { +            name: "odels;", +            characters: "\u{22a7}", +        }); +    } + +    if first_char == 'm' && try_read("stpos;") { +        return Some(CharRef { +            name: "stpos;", +            characters: "\u{223e}", +        }); +    } + +    if first_char == 'n' && try_read("VDash;") { +        return Some(CharRef { +            name: "VDash;", +            characters: "\u{22af}", +        }); +    } + +    if first_char == 'n' && try_read("Vdash;") { +        return Some(CharRef { +            name: "Vdash;", +            characters: "\u{22ae}", +        }); +    } + +    if first_char == 'n' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{144}", +        }); +    } + +    if first_char == 'n' && try_read("bumpe;") { +        return Some(CharRef { +            name: "bumpe;", +            characters: "\u{224f}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("caron;") { +        return Some(CharRef { +            name: "caron;", +            characters: "\u{148}", +        }); +    } + +    if first_char == 'n' && try_read("cedil;") { +        return Some(CharRef { +            name: "cedil;", +            characters: "\u{146}", +        }); +    } + +    if first_char == 'n' && try_read("earhk;") { +        return Some(CharRef { +            name: "earhk;", +            characters: "\u{2924}", +        }); +    } + +    if first_char == 'n' && try_read("equiv;") { +        return Some(CharRef { +            name: "equiv;", +            characters: "\u{2262}", +        }); +    } + +    if first_char == 'n' && try_read("esear;") { +        return Some(CharRef { +            name: "esear;", +            characters: "\u{2928}", +        }); +    } + +    if first_char == 'n' && try_read("exist;") { +        return Some(CharRef { +            name: "exist;", +            characters: "\u{2204}", +        }); +    } + +    if first_char == 'n' && try_read("ltrie;") { +        return Some(CharRef { +            name: "ltrie;", +            characters: "\u{22ec}", +        }); +    } + +    if first_char == 'n' && try_read("otinE;") { +        return Some(CharRef { +            name: "otinE;", +            characters: "\u{22f9}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("parsl;") { +        return Some(CharRef { +            name: "parsl;", +            characters: "\u{2afd}\u{20e5}", +        }); +    } + +    if first_char == 'n' && try_read("prcue;") { +        return Some(CharRef { +            name: "prcue;", +            characters: "\u{22e0}", +        }); +    } + +    if first_char == 'n' && try_read("rarrc;") { +        return Some(CharRef { +            name: "rarrc;", +            characters: "\u{2933}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("rarrw;") { +        return Some(CharRef { +            name: "rarrw;", +            characters: "\u{219d}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("rtrie;") { +        return Some(CharRef { +            name: "rtrie;", +            characters: "\u{22ed}", +        }); +    } + +    if first_char == 'n' && try_read("sccue;") { +        return Some(CharRef { +            name: "sccue;", +            characters: "\u{22e1}", +        }); +    } + +    if first_char == 'n' && try_read("simeq;") { +        return Some(CharRef { +            name: "simeq;", +            characters: "\u{2244}", +        }); +    } + +    if first_char == 'n' && try_read("tilde;") { +        return Some(CharRef { +            name: "tilde;", +            characters: "\u{f1}", +        }); +    } + +    if first_char == 'n' && try_read("umero;") { +        return Some(CharRef { +            name: "umero;", +            characters: "\u{2116}", +        }); +    } + +    if first_char == 'n' && try_read("vDash;") { +        return Some(CharRef { +            name: "vDash;", +            characters: "\u{22ad}", +        }); +    } + +    if first_char == 'n' && try_read("vHarr;") { +        return Some(CharRef { +            name: "vHarr;", +            characters: "\u{2904}", +        }); +    } + +    if first_char == 'n' && try_read("vdash;") { +        return Some(CharRef { +            name: "vdash;", +            characters: "\u{22ac}", +        }); +    } + +    if first_char == 'n' && try_read("vlArr;") { +        return Some(CharRef { +            name: "vlArr;", +            characters: "\u{2902}", +        }); +    } + +    if first_char == 'n' && try_read("vrArr;") { +        return Some(CharRef { +            name: "vrArr;", +            characters: "\u{2903}", +        }); +    } + +    if first_char == 'n' && try_read("warhk;") { +        return Some(CharRef { +            name: "warhk;", +            characters: "\u{2923}", +        }); +    } + +    if first_char == 'n' && try_read("wnear;") { +        return Some(CharRef { +            name: "wnear;", +            characters: "\u{2927}", +        }); +    } + +    if first_char == 'o' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{f3}", +        }); +    } + +    if first_char == 'o' && try_read("dblac;") { +        return Some(CharRef { +            name: "dblac;", +            characters: "\u{151}", +        }); +    } + +    if first_char == 'o' && try_read("dsold;") { +        return Some(CharRef { +            name: "dsold;", +            characters: "\u{29bc}", +        }); +    } + +    if first_char == 'o' && try_read("grave;") { +        return Some(CharRef { +            name: "grave;", +            characters: "\u{f2}", +        }); +    } + +    if first_char == 'o' && try_read("minus;") { +        return Some(CharRef { +            name: "minus;", +            characters: "\u{2296}", +        }); +    } + +    if first_char == 'o' && try_read("rigof;") { +        return Some(CharRef { +            name: "rigof;", +            characters: "\u{22b6}", +        }); +    } + +    if first_char == 'o' && try_read("slash;") { +        return Some(CharRef { +            name: "slash;", +            characters: "\u{f8}", +        }); +    } + +    if first_char == 'o' && try_read("tilde;") { +        return Some(CharRef { +            name: "tilde;", +            characters: "\u{f5}", +        }); +    } + +    if first_char == 'o' && try_read("times;") { +        return Some(CharRef { +            name: "times;", +            characters: "\u{2297}", +        }); +    } + +    if first_char == 'p' && try_read("arsim;") { +        return Some(CharRef { +            name: "arsim;", +            characters: "\u{2af3}", +        }); +    } + +    if first_char == 'p' && try_read("ercnt;") { +        return Some(CharRef { +            name: "ercnt;", +            characters: "\u{25}", +        }); +    } + +    if first_char == 'p' && try_read("eriod;") { +        return Some(CharRef { +            name: "eriod;", +            characters: "\u{2e}", +        }); +    } + +    if first_char == 'p' && try_read("ermil;") { +        return Some(CharRef { +            name: "ermil;", +            characters: "\u{2030}", +        }); +    } + +    if first_char == 'p' && try_read("hmmat;") { +        return Some(CharRef { +            name: "hmmat;", +            characters: "\u{2133}", +        }); +    } + +    if first_char == 'p' && try_read("lanck;") { +        return Some(CharRef { +            name: "lanck;", +            characters: "\u{210f}", +        }); +    } + +    if first_char == 'p' && try_read("lankv;") { +        return Some(CharRef { +            name: "lankv;", +            characters: "\u{210f}", +        }); +    } + +    if first_char == 'p' && try_read("lusdo;") { +        return Some(CharRef { +            name: "lusdo;", +            characters: "\u{2214}", +        }); +    } + +    if first_char == 'p' && try_read("lusdu;") { +        return Some(CharRef { +            name: "lusdu;", +            characters: "\u{2a25}", +        }); +    } + +    if first_char == 'p' && try_read("lusmn;") { +        return Some(CharRef { +            name: "lusmn;", +            characters: "\u{b1}", +        }); +    } + +    if first_char == 'p' && try_read("receq;") { +        return Some(CharRef { +            name: "receq;", +            characters: "\u{2aaf}", +        }); +    } + +    if first_char == 'p' && try_read("rimes;") { +        return Some(CharRef { +            name: "rimes;", +            characters: "\u{2119}", +        }); +    } + +    if first_char == 'p' && try_read("rnsim;") { +        return Some(CharRef { +            name: "rnsim;", +            characters: "\u{22e8}", +        }); +    } + +    if first_char == 'p' && try_read("ropto;") { +        return Some(CharRef { +            name: "ropto;", +            characters: "\u{221d}", +        }); +    } + +    if first_char == 'p' && try_read("rurel;") { +        return Some(CharRef { +            name: "rurel;", +            characters: "\u{22b0}", +        }); +    } + +    if first_char == 'p' && try_read("uncsp;") { +        return Some(CharRef { +            name: "uncsp;", +            characters: "\u{2008}", +        }); +    } + +    if first_char == 'q' && try_read("prime;") { +        return Some(CharRef { +            name: "prime;", +            characters: "\u{2057}", +        }); +    } + +    if first_char == 'r' && try_read("Atail;") { +        return Some(CharRef { +            name: "Atail;", +            characters: "\u{291c}", +        }); +    } + +    if first_char == 'r' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{155}", +        }); +    } + +    if first_char == 'r' && try_read("angle;") { +        return Some(CharRef { +            name: "angle;", +            characters: "\u{27e9}", +        }); +    } + +    if first_char == 'r' && try_read("arrap;") { +        return Some(CharRef { +            name: "arrap;", +            characters: "\u{2975}", +        }); +    } + +    if first_char == 'r' && try_read("arrfs;") { +        return Some(CharRef { +            name: "arrfs;", +            characters: "\u{291e}", +        }); +    } + +    if first_char == 'r' && try_read("arrhk;") { +        return Some(CharRef { +            name: "arrhk;", +            characters: "\u{21aa}", +        }); +    } + +    if first_char == 'r' && try_read("arrlp;") { +        return Some(CharRef { +            name: "arrlp;", +            characters: "\u{21ac}", +        }); +    } + +    if first_char == 'r' && try_read("arrpl;") { +        return Some(CharRef { +            name: "arrpl;", +            characters: "\u{2945}", +        }); +    } + +    if first_char == 'r' && try_read("arrtl;") { +        return Some(CharRef { +            name: "arrtl;", +            characters: "\u{21a3}", +        }); +    } + +    if first_char == 'r' && try_read("atail;") { +        return Some(CharRef { +            name: "atail;", +            characters: "\u{291a}", +        }); +    } + +    if first_char == 'r' && try_read("brace;") { +        return Some(CharRef { +            name: "brace;", +            characters: "\u{7d}", +        }); +    } + +    if first_char == 'r' && try_read("brack;") { +        return Some(CharRef { +            name: "brack;", +            characters: "\u{5d}", +        }); +    } + +    if first_char == 'r' && try_read("caron;") { +        return Some(CharRef { +            name: "caron;", +            characters: "\u{159}", +        }); +    } + +    if first_char == 'r' && try_read("cedil;") { +        return Some(CharRef { +            name: "cedil;", +            characters: "\u{157}", +        }); +    } + +    if first_char == 'r' && try_read("dquor;") { +        return Some(CharRef { +            name: "dquor;", +            characters: "\u{201d}", +        }); +    } + +    if first_char == 'r' && try_read("fisht;") { +        return Some(CharRef { +            name: "fisht;", +            characters: "\u{297d}", +        }); +    } + +    if first_char == 'r' && try_read("floor;") { +        return Some(CharRef { +            name: "floor;", +            characters: "\u{230b}", +        }); +    } + +    if first_char == 'r' && try_read("harul;") { +        return Some(CharRef { +            name: "harul;", +            characters: "\u{296c}", +        }); +    } + +    if first_char == 'r' && try_read("moust;") { +        return Some(CharRef { +            name: "moust;", +            characters: "\u{23b1}", +        }); +    } + +    if first_char == 'r' && try_read("oplus;") { +        return Some(CharRef { +            name: "oplus;", +            characters: "\u{2a2e}", +        }); +    } + +    if first_char == 'r' && try_read("pargt;") { +        return Some(CharRef { +            name: "pargt;", +            characters: "\u{2994}", +        }); +    } + +    if first_char == 'r' && try_read("saquo;") { +        return Some(CharRef { +            name: "saquo;", +            characters: "\u{203a}", +        }); +    } + +    if first_char == 'r' && try_read("squor;") { +        return Some(CharRef { +            name: "squor;", +            characters: "\u{2019}", +        }); +    } + +    if first_char == 'r' && try_read("three;") { +        return Some(CharRef { +            name: "three;", +            characters: "\u{22cc}", +        }); +    } + +    if first_char == 'r' && try_read("times;") { +        return Some(CharRef { +            name: "times;", +            characters: "\u{22ca}", +        }); +    } + +    if first_char == 's' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{15b}", +        }); +    } + +    if first_char == 's' && try_read("caron;") { +        return Some(CharRef { +            name: "caron;", +            characters: "\u{161}", +        }); +    } + +    if first_char == 's' && try_read("cedil;") { +        return Some(CharRef { +            name: "cedil;", +            characters: "\u{15f}", +        }); +    } + +    if first_char == 's' && try_read("cnsim;") { +        return Some(CharRef { +            name: "cnsim;", +            characters: "\u{22e9}", +        }); +    } + +    if first_char == 's' && try_read("earhk;") { +        return Some(CharRef { +            name: "earhk;", +            characters: "\u{2925}", +        }); +    } + +    if first_char == 's' && try_read("eswar;") { +        return Some(CharRef { +            name: "eswar;", +            characters: "\u{2929}", +        }); +    } + +    if first_char == 's' && try_read("frown;") { +        return Some(CharRef { +            name: "frown;", +            characters: "\u{2322}", +        }); +    } + +    if first_char == 's' && try_read("hchcy;") { +        return Some(CharRef { +            name: "hchcy;", +            characters: "\u{449}", +        }); +    } + +    if first_char == 's' && try_read("igmaf;") { +        return Some(CharRef { +            name: "igmaf;", +            characters: "\u{3c2}", +        }); +    } + +    if first_char == 's' && try_read("igmav;") { +        return Some(CharRef { +            name: "igmav;", +            characters: "\u{3c2}", +        }); +    } + +    if first_char == 's' && try_read("imdot;") { +        return Some(CharRef { +            name: "imdot;", +            characters: "\u{2a6a}", +        }); +    } + +    if first_char == 's' && try_read("mashp;") { +        return Some(CharRef { +            name: "mashp;", +            characters: "\u{2a33}", +        }); +    } + +    if first_char == 's' && try_read("oftcy;") { +        return Some(CharRef { +            name: "oftcy;", +            characters: "\u{44c}", +        }); +    } + +    if first_char == 's' && try_read("olbar;") { +        return Some(CharRef { +            name: "olbar;", +            characters: "\u{233f}", +        }); +    } + +    if first_char == 's' && try_read("pades;") { +        return Some(CharRef { +            name: "pades;", +            characters: "\u{2660}", +        }); +    } + +    if first_char == 's' && try_read("qcaps;") { +        return Some(CharRef { +            name: "qcaps;", +            characters: "\u{2293}\u{fe00}", +        }); +    } + +    if first_char == 's' && try_read("qcups;") { +        return Some(CharRef { +            name: "qcups;", +            characters: "\u{2294}\u{fe00}", +        }); +    } + +    if first_char == 's' && try_read("qsube;") { +        return Some(CharRef { +            name: "qsube;", +            characters: "\u{2291}", +        }); +    } + +    if first_char == 's' && try_read("qsupe;") { +        return Some(CharRef { +            name: "qsupe;", +            characters: "\u{2292}", +        }); +    } + +    if first_char == 's' && try_read("quare;") { +        return Some(CharRef { +            name: "quare;", +            characters: "\u{25a1}", +        }); +    } + +    if first_char == 's' && try_read("quarf;") { +        return Some(CharRef { +            name: "quarf;", +            characters: "\u{25aa}", +        }); +    } + +    if first_char == 's' && try_read("setmn;") { +        return Some(CharRef { +            name: "setmn;", +            characters: "\u{2216}", +        }); +    } + +    if first_char == 's' && try_read("smile;") { +        return Some(CharRef { +            name: "smile;", +            characters: "\u{2323}", +        }); +    } + +    if first_char == 's' && try_read("starf;") { +        return Some(CharRef { +            name: "starf;", +            characters: "\u{22c6}", +        }); +    } + +    if first_char == 's' && try_read("ubdot;") { +        return Some(CharRef { +            name: "ubdot;", +            characters: "\u{2abd}", +        }); +    } + +    if first_char == 's' && try_read("ubset;") { +        return Some(CharRef { +            name: "ubset;", +            characters: "\u{2282}", +        }); +    } + +    if first_char == 's' && try_read("ubsim;") { +        return Some(CharRef { +            name: "ubsim;", +            characters: "\u{2ac7}", +        }); +    } + +    if first_char == 's' && try_read("ubsub;") { +        return Some(CharRef { +            name: "ubsub;", +            characters: "\u{2ad5}", +        }); +    } + +    if first_char == 's' && try_read("ubsup;") { +        return Some(CharRef { +            name: "ubsup;", +            characters: "\u{2ad3}", +        }); +    } + +    if first_char == 's' && try_read("ucceq;") { +        return Some(CharRef { +            name: "ucceq;", +            characters: "\u{2ab0}", +        }); +    } + +    if first_char == 's' && try_read("updot;") { +        return Some(CharRef { +            name: "updot;", +            characters: "\u{2abe}", +        }); +    } + +    if first_char == 's' && try_read("upset;") { +        return Some(CharRef { +            name: "upset;", +            characters: "\u{2283}", +        }); +    } + +    if first_char == 's' && try_read("upsim;") { +        return Some(CharRef { +            name: "upsim;", +            characters: "\u{2ac8}", +        }); +    } + +    if first_char == 's' && try_read("upsub;") { +        return Some(CharRef { +            name: "upsub;", +            characters: "\u{2ad4}", +        }); +    } + +    if first_char == 's' && try_read("upsup;") { +        return Some(CharRef { +            name: "upsup;", +            characters: "\u{2ad6}", +        }); +    } + +    if first_char == 's' && try_read("warhk;") { +        return Some(CharRef { +            name: "warhk;", +            characters: "\u{2926}", +        }); +    } + +    if first_char == 's' && try_read("wnwar;") { +        return Some(CharRef { +            name: "wnwar;", +            characters: "\u{292a}", +        }); +    } + +    if first_char == 't' && try_read("arget;") { +        return Some(CharRef { +            name: "arget;", +            characters: "\u{2316}", +        }); +    } + +    if first_char == 't' && try_read("caron;") { +        return Some(CharRef { +            name: "caron;", +            characters: "\u{165}", +        }); +    } + +    if first_char == 't' && try_read("cedil;") { +        return Some(CharRef { +            name: "cedil;", +            characters: "\u{163}", +        }); +    } + +    if first_char == 't' && try_read("elrec;") { +        return Some(CharRef { +            name: "elrec;", +            characters: "\u{2315}", +        }); +    } + +    if first_char == 't' && try_read("here4;") { +        return Some(CharRef { +            name: "here4;", +            characters: "\u{2234}", +        }); +    } + +    if first_char == 't' && try_read("hetav;") { +        return Some(CharRef { +            name: "hetav;", +            characters: "\u{3d1}", +        }); +    } + +    if first_char == 't' && try_read("hinsp;") { +        return Some(CharRef { +            name: "hinsp;", +            characters: "\u{2009}", +        }); +    } + +    if first_char == 't' && try_read("hksim;") { +        return Some(CharRef { +            name: "hksim;", +            characters: "\u{223c}", +        }); +    } + +    if first_char == 't' && try_read("imesb;") { +        return Some(CharRef { +            name: "imesb;", +            characters: "\u{22a0}", +        }); +    } + +    if first_char == 't' && try_read("imesd;") { +        return Some(CharRef { +            name: "imesd;", +            characters: "\u{2a30}", +        }); +    } + +    if first_char == 't' && try_read("opbot;") { +        return Some(CharRef { +            name: "opbot;", +            characters: "\u{2336}", +        }); +    } + +    if first_char == 't' && try_read("opcir;") { +        return Some(CharRef { +            name: "opcir;", +            characters: "\u{2af1}", +        }); +    } + +    if first_char == 't' && try_read("prime;") { +        return Some(CharRef { +            name: "prime;", +            characters: "\u{2034}", +        }); +    } + +    if first_char == 't' && try_read("ridot;") { +        return Some(CharRef { +            name: "ridot;", +            characters: "\u{25ec}", +        }); +    } + +    if first_char == 't' && try_read("strok;") { +        return Some(CharRef { +            name: "strok;", +            characters: "\u{167}", +        }); +    } + +    if first_char == 'u' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{fa}", +        }); +    } + +    if first_char == 'u' && try_read("breve;") { +        return Some(CharRef { +            name: "breve;", +            characters: "\u{16d}", +        }); +    } + +    if first_char == 'u' && try_read("dblac;") { +        return Some(CharRef { +            name: "dblac;", +            characters: "\u{171}", +        }); +    } + +    if first_char == 'u' && try_read("fisht;") { +        return Some(CharRef { +            name: "fisht;", +            characters: "\u{297e}", +        }); +    } + +    if first_char == 'u' && try_read("grave;") { +        return Some(CharRef { +            name: "grave;", +            characters: "\u{f9}", +        }); +    } + +    if first_char == 'u' && try_read("lcorn;") { +        return Some(CharRef { +            name: "lcorn;", +            characters: "\u{231c}", +        }); +    } + +    if first_char == 'u' && try_read("lcrop;") { +        return Some(CharRef { +            name: "lcrop;", +            characters: "\u{230f}", +        }); +    } + +    if first_char == 'u' && try_read("rcorn;") { +        return Some(CharRef { +            name: "rcorn;", +            characters: "\u{231d}", +        }); +    } + +    if first_char == 'u' && try_read("rcrop;") { +        return Some(CharRef { +            name: "rcrop;", +            characters: "\u{230e}", +        }); +    } + +    if first_char == 'u' && try_read("tilde;") { +        return Some(CharRef { +            name: "tilde;", +            characters: "\u{169}", +        }); +    } + +    if first_char == 'v' && try_read("angrt;") { +        return Some(CharRef { +            name: "angrt;", +            characters: "\u{299c}", +        }); +    } + +    if first_char == 'v' && try_read("arphi;") { +        return Some(CharRef { +            name: "arphi;", +            characters: "\u{3d5}", +        }); +    } + +    if first_char == 'v' && try_read("arrho;") { +        return Some(CharRef { +            name: "arrho;", +            characters: "\u{3f1}", +        }); +    } + +    if first_char == 'v' && try_read("eebar;") { +        return Some(CharRef { +            name: "eebar;", +            characters: "\u{22bb}", +        }); +    } + +    if first_char == 'v' && try_read("ellip;") { +        return Some(CharRef { +            name: "ellip;", +            characters: "\u{22ee}", +        }); +    } + +    if first_char == 'v' && try_read("erbar;") { +        return Some(CharRef { +            name: "erbar;", +            characters: "\u{7c}", +        }); +    } + +    if first_char == 'v' && try_read("subnE;") { +        return Some(CharRef { +            name: "subnE;", +            characters: "\u{2acb}\u{fe00}", +        }); +    } + +    if first_char == 'v' && try_read("subne;") { +        return Some(CharRef { +            name: "subne;", +            characters: "\u{228a}\u{fe00}", +        }); +    } + +    if first_char == 'v' && try_read("supnE;") { +        return Some(CharRef { +            name: "supnE;", +            characters: "\u{2acc}\u{fe00}", +        }); +    } + +    if first_char == 'v' && try_read("supne;") { +        return Some(CharRef { +            name: "supne;", +            characters: "\u{228b}\u{fe00}", +        }); +    } + +    if first_char == 'w' && try_read("edbar;") { +        return Some(CharRef { +            name: "edbar;", +            characters: "\u{2a5f}", +        }); +    } + +    if first_char == 'w' && try_read("edgeq;") { +        return Some(CharRef { +            name: "edgeq;", +            characters: "\u{2259}", +        }); +    } + +    if first_char == 'w' && try_read("eierp;") { +        return Some(CharRef { +            name: "eierp;", +            characters: "\u{2118}", +        }); +    } + +    if first_char == 'w' && try_read("reath;") { +        return Some(CharRef { +            name: "reath;", +            characters: "\u{2240}", +        }); +    } + +    if first_char == 'x' && try_read("oplus;") { +        return Some(CharRef { +            name: "oplus;", +            characters: "\u{2a01}", +        }); +    } + +    if first_char == 'x' && try_read("otime;") { +        return Some(CharRef { +            name: "otime;", +            characters: "\u{2a02}", +        }); +    } + +    if first_char == 'x' && try_read("sqcup;") { +        return Some(CharRef { +            name: "sqcup;", +            characters: "\u{2a06}", +        }); +    } + +    if first_char == 'x' && try_read("uplus;") { +        return Some(CharRef { +            name: "uplus;", +            characters: "\u{2a04}", +        }); +    } + +    if first_char == 'x' && try_read("wedge;") { +        return Some(CharRef { +            name: "wedge;", +            characters: "\u{22c0}", +        }); +    } + +    if first_char == 'y' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{fd}", +        }); +    } + +    if first_char == 'z' && try_read("acute;") { +        return Some(CharRef { +            name: "acute;", +            characters: "\u{17a}", +        }); +    } + +    if first_char == 'z' && try_read("caron;") { +        return Some(CharRef { +            name: "caron;", +            characters: "\u{17e}", +        }); +    } + +    if first_char == 'z' && try_read("eetrf;") { +        return Some(CharRef { +            name: "eetrf;", +            characters: "\u{2128}", +        }); +    } + +    if first_char == 'A' && try_read("Elig;") { +        return Some(CharRef { +            name: "Elig;", +            characters: "\u{c6}", +        }); +    } + +    if first_char == 'A' && try_read("acute") { +        return Some(CharRef { +            name: "acute", +            characters: "\u{c1}", +        }); +    } + +    if first_char == 'A' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{c2}", +        }); +    } + +    if first_char == 'A' && try_read("grave") { +        return Some(CharRef { +            name: "grave", +            characters: "\u{c0}", +        }); +    } + +    if first_char == 'A' && try_read("lpha;") { +        return Some(CharRef { +            name: "lpha;", +            characters: "\u{391}", +        }); +    } + +    if first_char == 'A' && try_read("macr;") { +        return Some(CharRef { +            name: "macr;", +            characters: "\u{100}", +        }); +    } + +    if first_char == 'A' && try_read("ogon;") { +        return Some(CharRef { +            name: "ogon;", +            characters: "\u{104}", +        }); +    } + +    if first_char == 'A' && try_read("ring;") { +        return Some(CharRef { +            name: "ring;", +            characters: "\u{c5}", +        }); +    } + +    if first_char == 'A' && try_read("tilde") { +        return Some(CharRef { +            name: "tilde", +            characters: "\u{c3}", +        }); +    } + +    if first_char == 'B' && try_read("reve;") { +        return Some(CharRef { +            name: "reve;", +            characters: "\u{2d8}", +        }); +    } + +    if first_char == 'C' && try_read("cedil") { +        return Some(CharRef { +            name: "cedil", +            characters: "\u{c7}", +        }); +    } + +    if first_char == 'C' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{108}", +        }); +    } + +    if first_char == 'C' && try_read("olon;") { +        return Some(CharRef { +            name: "olon;", +            characters: "\u{2237}", +        }); +    } + +    if first_char == 'C' && try_read("ross;") { +        return Some(CharRef { +            name: "ross;", +            characters: "\u{2a2f}", +        }); +    } + +    if first_char == 'D' && try_read("ashv;") { +        return Some(CharRef { +            name: "ashv;", +            characters: "\u{2ae4}", +        }); +    } + +    if first_char == 'D' && try_read("elta;") { +        return Some(CharRef { +            name: "elta;", +            characters: "\u{394}", +        }); +    } + +    if first_char == 'E' && try_read("acute") { +        return Some(CharRef { +            name: "acute", +            characters: "\u{c9}", +        }); +    } + +    if first_char == 'E' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{ca}", +        }); +    } + +    if first_char == 'E' && try_read("grave") { +        return Some(CharRef { +            name: "grave", +            characters: "\u{c8}", +        }); +    } + +    if first_char == 'E' && try_read("macr;") { +        return Some(CharRef { +            name: "macr;", +            characters: "\u{112}", +        }); +    } + +    if first_char == 'E' && try_read("ogon;") { +        return Some(CharRef { +            name: "ogon;", +            characters: "\u{118}", +        }); +    } + +    if first_char == 'E' && try_read("qual;") { +        return Some(CharRef { +            name: "qual;", +            characters: "\u{2a75}", +        }); +    } + +    if first_char == 'G' && try_read("amma;") { +        return Some(CharRef { +            name: "amma;", +            characters: "\u{393}", +        }); +    } + +    if first_char == 'G' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{11c}", +        }); +    } + +    if first_char == 'H' && try_read("acek;") { +        return Some(CharRef { +            name: "acek;", +            characters: "\u{2c7}", +        }); +    } + +    if first_char == 'H' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{124}", +        }); +    } + +    if first_char == 'I' && try_read("Jlig;") { +        return Some(CharRef { +            name: "Jlig;", +            characters: "\u{132}", +        }); +    } + +    if first_char == 'I' && try_read("acute") { +        return Some(CharRef { +            name: "acute", +            characters: "\u{cd}", +        }); +    } + +    if first_char == 'I' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{ce}", +        }); +    } + +    if first_char == 'I' && try_read("grave") { +        return Some(CharRef { +            name: "grave", +            characters: "\u{cc}", +        }); +    } + +    if first_char == 'I' && try_read("macr;") { +        return Some(CharRef { +            name: "macr;", +            characters: "\u{12a}", +        }); +    } + +    if first_char == 'I' && try_read("ogon;") { +        return Some(CharRef { +            name: "ogon;", +            characters: "\u{12e}", +        }); +    } + +    if first_char == 'I' && try_read("ukcy;") { +        return Some(CharRef { +            name: "ukcy;", +            characters: "\u{406}", +        }); +    } + +    if first_char == 'J' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{134}", +        }); +    } + +    if first_char == 'J' && try_read("ukcy;") { +        return Some(CharRef { +            name: "ukcy;", +            characters: "\u{404}", +        }); +    } + +    if first_char == 'K' && try_read("appa;") { +        return Some(CharRef { +            name: "appa;", +            characters: "\u{39a}", +        }); +    } + +    if first_char == 'N' && try_read("tilde") { +        return Some(CharRef { +            name: "tilde", +            characters: "\u{d1}", +        }); +    } + +    if first_char == 'O' && try_read("Elig;") { +        return Some(CharRef { +            name: "Elig;", +            characters: "\u{152}", +        }); +    } + +    if first_char == 'O' && try_read("acute") { +        return Some(CharRef { +            name: "acute", +            characters: "\u{d3}", +        }); +    } + +    if first_char == 'O' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{d4}", +        }); +    } + +    if first_char == 'O' && try_read("grave") { +        return Some(CharRef { +            name: "grave", +            characters: "\u{d2}", +        }); +    } + +    if first_char == 'O' && try_read("macr;") { +        return Some(CharRef { +            name: "macr;", +            characters: "\u{14c}", +        }); +    } + +    if first_char == 'O' && try_read("mega;") { +        return Some(CharRef { +            name: "mega;", +            characters: "\u{3a9}", +        }); +    } + +    if first_char == 'O' && try_read("slash") { +        return Some(CharRef { +            name: "slash", +            characters: "\u{d8}", +        }); +    } + +    if first_char == 'O' && try_read("tilde") { +        return Some(CharRef { +            name: "tilde", +            characters: "\u{d5}", +        }); +    } + +    if first_char == 'P' && try_read("rime;") { +        return Some(CharRef { +            name: "rime;", +            characters: "\u{2033}", +        }); +    } + +    if first_char == 'R' && try_read("Barr;") { +        return Some(CharRef { +            name: "Barr;", +            characters: "\u{2910}", +        }); +    } + +    if first_char == 'S' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{15c}", +        }); +    } + +    if first_char == 'S' && try_read("igma;") { +        return Some(CharRef { +            name: "igma;", +            characters: "\u{3a3}", +        }); +    } + +    if first_char == 'T' && try_read("HORN;") { +        return Some(CharRef { +            name: "HORN;", +            characters: "\u{de}", +        }); +    } + +    if first_char == 'T' && try_read("RADE;") { +        return Some(CharRef { +            name: "RADE;", +            characters: "\u{2122}", +        }); +    } + +    if first_char == 'T' && try_read("SHcy;") { +        return Some(CharRef { +            name: "SHcy;", +            characters: "\u{40b}", +        }); +    } + +    if first_char == 'T' && try_read("heta;") { +        return Some(CharRef { +            name: "heta;", +            characters: "\u{398}", +        }); +    } + +    if first_char == 'T' && try_read("ilde;") { +        return Some(CharRef { +            name: "ilde;", +            characters: "\u{223c}", +        }); +    } + +    if first_char == 'U' && try_read("acute") { +        return Some(CharRef { +            name: "acute", +            characters: "\u{da}", +        }); +    } + +    if first_char == 'U' && try_read("brcy;") { +        return Some(CharRef { +            name: "brcy;", +            characters: "\u{40e}", +        }); +    } + +    if first_char == 'U' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{db}", +        }); +    } + +    if first_char == 'U' && try_read("grave") { +        return Some(CharRef { +            name: "grave", +            characters: "\u{d9}", +        }); +    } + +    if first_char == 'U' && try_read("macr;") { +        return Some(CharRef { +            name: "macr;", +            characters: "\u{16a}", +        }); +    } + +    if first_char == 'U' && try_read("nion;") { +        return Some(CharRef { +            name: "nion;", +            characters: "\u{22c3}", +        }); +    } + +    if first_char == 'U' && try_read("ogon;") { +        return Some(CharRef { +            name: "ogon;", +            characters: "\u{172}", +        }); +    } + +    if first_char == 'U' && try_read("pTee;") { +        return Some(CharRef { +            name: "pTee;", +            characters: "\u{22a5}", +        }); +    } + +    if first_char == 'U' && try_read("ring;") { +        return Some(CharRef { +            name: "ring;", +            characters: "\u{16e}", +        }); +    } + +    if first_char == 'V' && try_read("Dash;") { +        return Some(CharRef { +            name: "Dash;", +            characters: "\u{22ab}", +        }); +    } + +    if first_char == 'V' && try_read("dash;") { +        return Some(CharRef { +            name: "dash;", +            characters: "\u{22a9}", +        }); +    } + +    if first_char == 'W' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{174}", +        }); +    } + +    if first_char == 'W' && try_read("edge;") { +        return Some(CharRef { +            name: "edge;", +            characters: "\u{22c0}", +        }); +    } + +    if first_char == 'Y' && try_read("acute") { +        return Some(CharRef { +            name: "acute", +            characters: "\u{dd}", +        }); +    } + +    if first_char == 'Y' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{176}", +        }); +    } + +    if first_char == 'a' && try_read("acute") { +        return Some(CharRef { +            name: "acute", +            characters: "\u{e1}", +        }); +    } + +    if first_char == 'a' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{e2}", +        }); +    } + +    if first_char == 'a' && try_read("cute;") { +        return Some(CharRef { +            name: "cute;", +            characters: "\u{b4}", +        }); +    } + +    if first_char == 'a' && try_read("elig;") { +        return Some(CharRef { +            name: "elig;", +            characters: "\u{e6}", +        }); +    } + +    if first_char == 'a' && try_read("grave") { +        return Some(CharRef { +            name: "grave", +            characters: "\u{e0}", +        }); +    } + +    if first_char == 'a' && try_read("leph;") { +        return Some(CharRef { +            name: "leph;", +            characters: "\u{2135}", +        }); +    } + +    if first_char == 'a' && try_read("lpha;") { +        return Some(CharRef { +            name: "lpha;", +            characters: "\u{3b1}", +        }); +    } + +    if first_char == 'a' && try_read("macr;") { +        return Some(CharRef { +            name: "macr;", +            characters: "\u{101}", +        }); +    } + +    if first_char == 'a' && try_read("malg;") { +        return Some(CharRef { +            name: "malg;", +            characters: "\u{2a3f}", +        }); +    } + +    if first_char == 'a' && try_read("ngle;") { +        return Some(CharRef { +            name: "ngle;", +            characters: "\u{2220}", +        }); +    } + +    if first_char == 'a' && try_read("ngrt;") { +        return Some(CharRef { +            name: "ngrt;", +            characters: "\u{221f}", +        }); +    } + +    if first_char == 'a' && try_read("ngst;") { +        return Some(CharRef { +            name: "ngst;", +            characters: "\u{c5}", +        }); +    } + +    if first_char == 'a' && try_read("ogon;") { +        return Some(CharRef { +            name: "ogon;", +            characters: "\u{105}", +        }); +    } + +    if first_char == 'a' && try_read("ring;") { +        return Some(CharRef { +            name: "ring;", +            characters: "\u{e5}", +        }); +    } + +    if first_char == 'a' && try_read("symp;") { +        return Some(CharRef { +            name: "symp;", +            characters: "\u{2248}", +        }); +    } + +    if first_char == 'a' && try_read("tilde") { +        return Some(CharRef { +            name: "tilde", +            characters: "\u{e3}", +        }); +    } + +    if first_char == 'a' && try_read("wint;") { +        return Some(CharRef { +            name: "wint;", +            characters: "\u{2a11}", +        }); +    } + +    if first_char == 'b' && try_read("cong;") { +        return Some(CharRef { +            name: "cong;", +            characters: "\u{224c}", +        }); +    } + +    if first_char == 'b' && try_read("dquo;") { +        return Some(CharRef { +            name: "dquo;", +            characters: "\u{201e}", +        }); +    } + +    if first_char == 'b' && try_read("epsi;") { +        return Some(CharRef { +            name: "epsi;", +            characters: "\u{3f6}", +        }); +    } + +    if first_char == 'b' && try_read("lank;") { +        return Some(CharRef { +            name: "lank;", +            characters: "\u{2423}", +        }); +    } + +    if first_char == 'b' && try_read("lk12;") { +        return Some(CharRef { +            name: "lk12;", +            characters: "\u{2592}", +        }); +    } + +    if first_char == 'b' && try_read("lk14;") { +        return Some(CharRef { +            name: "lk14;", +            characters: "\u{2591}", +        }); +    } + +    if first_char == 'b' && try_read("lk34;") { +        return Some(CharRef { +            name: "lk34;", +            characters: "\u{2593}", +        }); +    } + +    if first_char == 'b' && try_read("lock;") { +        return Some(CharRef { +            name: "lock;", +            characters: "\u{2588}", +        }); +    } + +    if first_char == 'b' && try_read("oxDL;") { +        return Some(CharRef { +            name: "oxDL;", +            characters: "\u{2557}", +        }); +    } + +    if first_char == 'b' && try_read("oxDR;") { +        return Some(CharRef { +            name: "oxDR;", +            characters: "\u{2554}", +        }); +    } + +    if first_char == 'b' && try_read("oxDl;") { +        return Some(CharRef { +            name: "oxDl;", +            characters: "\u{2556}", +        }); +    } + +    if first_char == 'b' && try_read("oxDr;") { +        return Some(CharRef { +            name: "oxDr;", +            characters: "\u{2553}", +        }); +    } + +    if first_char == 'b' && try_read("oxHD;") { +        return Some(CharRef { +            name: "oxHD;", +            characters: "\u{2566}", +        }); +    } + +    if first_char == 'b' && try_read("oxHU;") { +        return Some(CharRef { +            name: "oxHU;", +            characters: "\u{2569}", +        }); +    } + +    if first_char == 'b' && try_read("oxHd;") { +        return Some(CharRef { +            name: "oxHd;", +            characters: "\u{2564}", +        }); +    } + +    if first_char == 'b' && try_read("oxHu;") { +        return Some(CharRef { +            name: "oxHu;", +            characters: "\u{2567}", +        }); +    } + +    if first_char == 'b' && try_read("oxUL;") { +        return Some(CharRef { +            name: "oxUL;", +            characters: "\u{255d}", +        }); +    } + +    if first_char == 'b' && try_read("oxUR;") { +        return Some(CharRef { +            name: "oxUR;", +            characters: "\u{255a}", +        }); +    } + +    if first_char == 'b' && try_read("oxUl;") { +        return Some(CharRef { +            name: "oxUl;", +            characters: "\u{255c}", +        }); +    } + +    if first_char == 'b' && try_read("oxUr;") { +        return Some(CharRef { +            name: "oxUr;", +            characters: "\u{2559}", +        }); +    } + +    if first_char == 'b' && try_read("oxVH;") { +        return Some(CharRef { +            name: "oxVH;", +            characters: "\u{256c}", +        }); +    } + +    if first_char == 'b' && try_read("oxVL;") { +        return Some(CharRef { +            name: "oxVL;", +            characters: "\u{2563}", +        }); +    } + +    if first_char == 'b' && try_read("oxVR;") { +        return Some(CharRef { +            name: "oxVR;", +            characters: "\u{2560}", +        }); +    } + +    if first_char == 'b' && try_read("oxVh;") { +        return Some(CharRef { +            name: "oxVh;", +            characters: "\u{256b}", +        }); +    } + +    if first_char == 'b' && try_read("oxVl;") { +        return Some(CharRef { +            name: "oxVl;", +            characters: "\u{2562}", +        }); +    } + +    if first_char == 'b' && try_read("oxVr;") { +        return Some(CharRef { +            name: "oxVr;", +            characters: "\u{255f}", +        }); +    } + +    if first_char == 'b' && try_read("oxdL;") { +        return Some(CharRef { +            name: "oxdL;", +            characters: "\u{2555}", +        }); +    } + +    if first_char == 'b' && try_read("oxdR;") { +        return Some(CharRef { +            name: "oxdR;", +            characters: "\u{2552}", +        }); +    } + +    if first_char == 'b' && try_read("oxdl;") { +        return Some(CharRef { +            name: "oxdl;", +            characters: "\u{2510}", +        }); +    } + +    if first_char == 'b' && try_read("oxdr;") { +        return Some(CharRef { +            name: "oxdr;", +            characters: "\u{250c}", +        }); +    } + +    if first_char == 'b' && try_read("oxhD;") { +        return Some(CharRef { +            name: "oxhD;", +            characters: "\u{2565}", +        }); +    } + +    if first_char == 'b' && try_read("oxhU;") { +        return Some(CharRef { +            name: "oxhU;", +            characters: "\u{2568}", +        }); +    } + +    if first_char == 'b' && try_read("oxhd;") { +        return Some(CharRef { +            name: "oxhd;", +            characters: "\u{252c}", +        }); +    } + +    if first_char == 'b' && try_read("oxhu;") { +        return Some(CharRef { +            name: "oxhu;", +            characters: "\u{2534}", +        }); +    } + +    if first_char == 'b' && try_read("oxuL;") { +        return Some(CharRef { +            name: "oxuL;", +            characters: "\u{255b}", +        }); +    } + +    if first_char == 'b' && try_read("oxuR;") { +        return Some(CharRef { +            name: "oxuR;", +            characters: "\u{2558}", +        }); +    } + +    if first_char == 'b' && try_read("oxul;") { +        return Some(CharRef { +            name: "oxul;", +            characters: "\u{2518}", +        }); +    } + +    if first_char == 'b' && try_read("oxur;") { +        return Some(CharRef { +            name: "oxur;", +            characters: "\u{2514}", +        }); +    } + +    if first_char == 'b' && try_read("oxvH;") { +        return Some(CharRef { +            name: "oxvH;", +            characters: "\u{256a}", +        }); +    } + +    if first_char == 'b' && try_read("oxvL;") { +        return Some(CharRef { +            name: "oxvL;", +            characters: "\u{2561}", +        }); +    } + +    if first_char == 'b' && try_read("oxvR;") { +        return Some(CharRef { +            name: "oxvR;", +            characters: "\u{255e}", +        }); +    } + +    if first_char == 'b' && try_read("oxvh;") { +        return Some(CharRef { +            name: "oxvh;", +            characters: "\u{253c}", +        }); +    } + +    if first_char == 'b' && try_read("oxvl;") { +        return Some(CharRef { +            name: "oxvl;", +            characters: "\u{2524}", +        }); +    } + +    if first_char == 'b' && try_read("oxvr;") { +        return Some(CharRef { +            name: "oxvr;", +            characters: "\u{251c}", +        }); +    } + +    if first_char == 'b' && try_read("reve;") { +        return Some(CharRef { +            name: "reve;", +            characters: "\u{2d8}", +        }); +    } + +    if first_char == 'b' && try_read("rvbar") { +        return Some(CharRef { +            name: "rvbar", +            characters: "\u{a6}", +        }); +    } + +    if first_char == 'b' && try_read("semi;") { +        return Some(CharRef { +            name: "semi;", +            characters: "\u{204f}", +        }); +    } + +    if first_char == 'b' && try_read("sime;") { +        return Some(CharRef { +            name: "sime;", +            characters: "\u{22cd}", +        }); +    } + +    if first_char == 'b' && try_read("solb;") { +        return Some(CharRef { +            name: "solb;", +            characters: "\u{29c5}", +        }); +    } + +    if first_char == 'b' && try_read("umpE;") { +        return Some(CharRef { +            name: "umpE;", +            characters: "\u{2aae}", +        }); +    } + +    if first_char == 'b' && try_read("umpe;") { +        return Some(CharRef { +            name: "umpe;", +            characters: "\u{224f}", +        }); +    } + +    if first_char == 'c' && try_read("aret;") { +        return Some(CharRef { +            name: "aret;", +            characters: "\u{2041}", +        }); +    } + +    if first_char == 'c' && try_read("aron;") { +        return Some(CharRef { +            name: "aron;", +            characters: "\u{2c7}", +        }); +    } + +    if first_char == 'c' && try_read("caps;") { +        return Some(CharRef { +            name: "caps;", +            characters: "\u{2a4d}", +        }); +    } + +    if first_char == 'c' && try_read("cedil") { +        return Some(CharRef { +            name: "cedil", +            characters: "\u{e7}", +        }); +    } + +    if first_char == 'c' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{109}", +        }); +    } + +    if first_char == 'c' && try_read("cups;") { +        return Some(CharRef { +            name: "cups;", +            characters: "\u{2a4c}", +        }); +    } + +    if first_char == 'c' && try_read("edil;") { +        return Some(CharRef { +            name: "edil;", +            characters: "\u{b8}", +        }); +    } + +    if first_char == 'c' && try_read("heck;") { +        return Some(CharRef { +            name: "heck;", +            characters: "\u{2713}", +        }); +    } + +    if first_char == 'c' && try_read("lubs;") { +        return Some(CharRef { +            name: "lubs;", +            characters: "\u{2663}", +        }); +    } + +    if first_char == 'c' && try_read("olon;") { +        return Some(CharRef { +            name: "olon;", +            characters: "\u{3a}", +        }); +    } + +    if first_char == 'c' && try_read("omma;") { +        return Some(CharRef { +            name: "omma;", +            characters: "\u{2c}", +        }); +    } + +    if first_char == 'c' && try_read("rarr;") { +        return Some(CharRef { +            name: "rarr;", +            characters: "\u{21b5}", +        }); +    } + +    if first_char == 'c' && try_read("ross;") { +        return Some(CharRef { +            name: "ross;", +            characters: "\u{2717}", +        }); +    } + +    if first_char == 'c' && try_read("sube;") { +        return Some(CharRef { +            name: "sube;", +            characters: "\u{2ad1}", +        }); +    } + +    if first_char == 'c' && try_read("supe;") { +        return Some(CharRef { +            name: "supe;", +            characters: "\u{2ad2}", +        }); +    } + +    if first_char == 'c' && try_read("tdot;") { +        return Some(CharRef { +            name: "tdot;", +            characters: "\u{22ef}", +        }); +    } + +    if first_char == 'c' && try_read("uepr;") { +        return Some(CharRef { +            name: "uepr;", +            characters: "\u{22de}", +        }); +    } + +    if first_char == 'c' && try_read("uesc;") { +        return Some(CharRef { +            name: "uesc;", +            characters: "\u{22df}", +        }); +    } + +    if first_char == 'c' && try_read("upor;") { +        return Some(CharRef { +            name: "upor;", +            characters: "\u{2a45}", +        }); +    } + +    if first_char == 'c' && try_read("urren") { +        return Some(CharRef { +            name: "urren", +            characters: "\u{a4}", +        }); +    } + +    if first_char == 'c' && try_read("uvee;") { +        return Some(CharRef { +            name: "uvee;", +            characters: "\u{22ce}", +        }); +    } + +    if first_char == 'c' && try_read("uwed;") { +        return Some(CharRef { +            name: "uwed;", +            characters: "\u{22cf}", +        }); +    } + +    if first_char == 'c' && try_read("wint;") { +        return Some(CharRef { +            name: "wint;", +            characters: "\u{2231}", +        }); +    } + +    if first_char == 'd' && try_read("ashv;") { +        return Some(CharRef { +            name: "ashv;", +            characters: "\u{22a3}", +        }); +    } + +    if first_char == 'd' && try_read("blac;") { +        return Some(CharRef { +            name: "blac;", +            characters: "\u{2dd}", +        }); +    } + +    if first_char == 'd' && try_read("darr;") { +        return Some(CharRef { +            name: "darr;", +            characters: "\u{21ca}", +        }); +    } + +    if first_char == 'd' && try_read("elta;") { +        return Some(CharRef { +            name: "elta;", +            characters: "\u{3b4}", +        }); +    } + +    if first_char == 'd' && try_read("harl;") { +        return Some(CharRef { +            name: "harl;", +            characters: "\u{21c3}", +        }); +    } + +    if first_char == 'd' && try_read("harr;") { +        return Some(CharRef { +            name: "harr;", +            characters: "\u{21c2}", +        }); +    } + +    if first_char == 'd' && try_read("iams;") { +        return Some(CharRef { +            name: "iams;", +            characters: "\u{2666}", +        }); +    } + +    if first_char == 'd' && try_read("isin;") { +        return Some(CharRef { +            name: "isin;", +            characters: "\u{22f2}", +        }); +    } + +    if first_char == 'd' && try_read("ivide") { +        return Some(CharRef { +            name: "ivide", +            characters: "\u{f7}", +        }); +    } + +    if first_char == 'd' && try_read("oteq;") { +        return Some(CharRef { +            name: "oteq;", +            characters: "\u{2250}", +        }); +    } + +    if first_char == 'd' && try_read("tdot;") { +        return Some(CharRef { +            name: "tdot;", +            characters: "\u{22f1}", +        }); +    } + +    if first_char == 'd' && try_read("trif;") { +        return Some(CharRef { +            name: "trif;", +            characters: "\u{25be}", +        }); +    } + +    if first_char == 'd' && try_read("uarr;") { +        return Some(CharRef { +            name: "uarr;", +            characters: "\u{21f5}", +        }); +    } + +    if first_char == 'd' && try_read("uhar;") { +        return Some(CharRef { +            name: "uhar;", +            characters: "\u{296f}", +        }); +    } + +    if first_char == 'e' && try_read("DDot;") { +        return Some(CharRef { +            name: "DDot;", +            characters: "\u{2a77}", +        }); +    } + +    if first_char == 'e' && try_read("acute") { +        return Some(CharRef { +            name: "acute", +            characters: "\u{e9}", +        }); +    } + +    if first_char == 'e' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{ea}", +        }); +    } + +    if first_char == 'e' && try_read("fDot;") { +        return Some(CharRef { +            name: "fDot;", +            characters: "\u{2252}", +        }); +    } + +    if first_char == 'e' && try_read("grave") { +        return Some(CharRef { +            name: "grave", +            characters: "\u{e8}", +        }); +    } + +    if first_char == 'e' && try_read("macr;") { +        return Some(CharRef { +            name: "macr;", +            characters: "\u{113}", +        }); +    } + +    if first_char == 'e' && try_read("mpty;") { +        return Some(CharRef { +            name: "mpty;", +            characters: "\u{2205}", +        }); +    } + +    if first_char == 'e' && try_read("ogon;") { +        return Some(CharRef { +            name: "ogon;", +            characters: "\u{119}", +        }); +    } + +    if first_char == 'e' && try_read("plus;") { +        return Some(CharRef { +            name: "plus;", +            characters: "\u{2a71}", +        }); +    } + +    if first_char == 'e' && try_read("psiv;") { +        return Some(CharRef { +            name: "psiv;", +            characters: "\u{3f5}", +        }); +    } + +    if first_char == 'e' && try_read("qsim;") { +        return Some(CharRef { +            name: "qsim;", +            characters: "\u{2242}", +        }); +    } + +    if first_char == 'e' && try_read("quiv;") { +        return Some(CharRef { +            name: "quiv;", +            characters: "\u{2261}", +        }); +    } + +    if first_char == 'e' && try_read("rDot;") { +        return Some(CharRef { +            name: "rDot;", +            characters: "\u{2253}", +        }); +    } + +    if first_char == 'e' && try_read("rarr;") { +        return Some(CharRef { +            name: "rarr;", +            characters: "\u{2971}", +        }); +    } + +    if first_char == 'e' && try_read("sdot;") { +        return Some(CharRef { +            name: "sdot;", +            characters: "\u{2250}", +        }); +    } + +    if first_char == 'e' && try_read("xist;") { +        return Some(CharRef { +            name: "xist;", +            characters: "\u{2203}", +        }); +    } + +    if first_char == 'f' && try_read("flig;") { +        return Some(CharRef { +            name: "flig;", +            characters: "\u{fb00}", +        }); +    } + +    if first_char == 'f' && try_read("ilig;") { +        return Some(CharRef { +            name: "ilig;", +            characters: "\u{fb01}", +        }); +    } + +    if first_char == 'f' && try_read("jlig;") { +        return Some(CharRef { +            name: "jlig;", +            characters: "\u{66}\u{6a}", +        }); +    } + +    if first_char == 'f' && try_read("llig;") { +        return Some(CharRef { +            name: "llig;", +            characters: "\u{fb02}", +        }); +    } + +    if first_char == 'f' && try_read("ltns;") { +        return Some(CharRef { +            name: "ltns;", +            characters: "\u{25b1}", +        }); +    } + +    if first_char == 'f' && try_read("orkv;") { +        return Some(CharRef { +            name: "orkv;", +            characters: "\u{2ad9}", +        }); +    } + +    if first_char == 'f' && try_read("rac12") { +        return Some(CharRef { +            name: "rac12", +            characters: "\u{bd}", +        }); +    } + +    if first_char == 'f' && try_read("rac14") { +        return Some(CharRef { +            name: "rac14", +            characters: "\u{bc}", +        }); +    } + +    if first_char == 'f' && try_read("rac34") { +        return Some(CharRef { +            name: "rac34", +            characters: "\u{be}", +        }); +    } + +    if first_char == 'f' && try_read("rasl;") { +        return Some(CharRef { +            name: "rasl;", +            characters: "\u{2044}", +        }); +    } + +    if first_char == 'f' && try_read("rown;") { +        return Some(CharRef { +            name: "rown;", +            characters: "\u{2322}", +        }); +    } + +    if first_char == 'g' && try_read("amma;") { +        return Some(CharRef { +            name: "amma;", +            characters: "\u{3b3}", +        }); +    } + +    if first_char == 'g' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{11d}", +        }); +    } + +    if first_char == 'g' && try_read("escc;") { +        return Some(CharRef { +            name: "escc;", +            characters: "\u{2aa9}", +        }); +    } + +    if first_char == 'g' && try_read("imel;") { +        return Some(CharRef { +            name: "imel;", +            characters: "\u{2137}", +        }); +    } + +    if first_char == 'g' && try_read("neqq;") { +        return Some(CharRef { +            name: "neqq;", +            characters: "\u{2269}", +        }); +    } + +    if first_char == 'g' && try_read("nsim;") { +        return Some(CharRef { +            name: "nsim;", +            characters: "\u{22e7}", +        }); +    } + +    if first_char == 'g' && try_read("rave;") { +        return Some(CharRef { +            name: "rave;", +            characters: "\u{60}", +        }); +    } + +    if first_char == 'g' && try_read("sime;") { +        return Some(CharRef { +            name: "sime;", +            characters: "\u{2a8e}", +        }); +    } + +    if first_char == 'g' && try_read("siml;") { +        return Some(CharRef { +            name: "siml;", +            characters: "\u{2a90}", +        }); +    } + +    if first_char == 'g' && try_read("tcir;") { +        return Some(CharRef { +            name: "tcir;", +            characters: "\u{2a7a}", +        }); +    } + +    if first_char == 'g' && try_read("tdot;") { +        return Some(CharRef { +            name: "tdot;", +            characters: "\u{22d7}", +        }); +    } + +    if first_char == 'h' && try_read("arrw;") { +        return Some(CharRef { +            name: "arrw;", +            characters: "\u{21ad}", +        }); +    } + +    if first_char == 'h' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{125}", +        }); +    } + +    if first_char == 'h' && try_read("oarr;") { +        return Some(CharRef { +            name: "oarr;", +            characters: "\u{21ff}", +        }); +    } + +    if first_char == 'i' && try_read("acute") { +        return Some(CharRef { +            name: "acute", +            characters: "\u{ed}", +        }); +    } + +    if first_char == 'i' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{ee}", +        }); +    } + +    if first_char == 'i' && try_read("excl;") { +        return Some(CharRef { +            name: "excl;", +            characters: "\u{a1}", +        }); +    } + +    if first_char == 'i' && try_read("grave") { +        return Some(CharRef { +            name: "grave", +            characters: "\u{ec}", +        }); +    } + +    if first_char == 'i' && try_read("iint;") { +        return Some(CharRef { +            name: "iint;", +            characters: "\u{222d}", +        }); +    } + +    if first_char == 'i' && try_read("iota;") { +        return Some(CharRef { +            name: "iota;", +            characters: "\u{2129}", +        }); +    } + +    if first_char == 'i' && try_read("jlig;") { +        return Some(CharRef { +            name: "jlig;", +            characters: "\u{133}", +        }); +    } + +    if first_char == 'i' && try_read("macr;") { +        return Some(CharRef { +            name: "macr;", +            characters: "\u{12b}", +        }); +    } + +    if first_char == 'i' && try_read("mage;") { +        return Some(CharRef { +            name: "mage;", +            characters: "\u{2111}", +        }); +    } + +    if first_char == 'i' && try_read("math;") { +        return Some(CharRef { +            name: "math;", +            characters: "\u{131}", +        }); +    } + +    if first_char == 'i' && try_read("mped;") { +        return Some(CharRef { +            name: "mped;", +            characters: "\u{1b5}", +        }); +    } + +    if first_char == 'i' && try_read("nfin;") { +        return Some(CharRef { +            name: "nfin;", +            characters: "\u{221e}", +        }); +    } + +    if first_char == 'i' && try_read("ogon;") { +        return Some(CharRef { +            name: "ogon;", +            characters: "\u{12f}", +        }); +    } + +    if first_char == 'i' && try_read("prod;") { +        return Some(CharRef { +            name: "prod;", +            characters: "\u{2a3c}", +        }); +    } + +    if first_char == 'i' && try_read("quest") { +        return Some(CharRef { +            name: "quest", +            characters: "\u{bf}", +        }); +    } + +    if first_char == 'i' && try_read("sinE;") { +        return Some(CharRef { +            name: "sinE;", +            characters: "\u{22f9}", +        }); +    } + +    if first_char == 'i' && try_read("sins;") { +        return Some(CharRef { +            name: "sins;", +            characters: "\u{22f4}", +        }); +    } + +    if first_char == 'i' && try_read("sinv;") { +        return Some(CharRef { +            name: "sinv;", +            characters: "\u{2208}", +        }); +    } + +    if first_char == 'i' && try_read("ukcy;") { +        return Some(CharRef { +            name: "ukcy;", +            characters: "\u{456}", +        }); +    } + +    if first_char == 'j' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{135}", +        }); +    } + +    if first_char == 'j' && try_read("math;") { +        return Some(CharRef { +            name: "math;", +            characters: "\u{237}", +        }); +    } + +    if first_char == 'j' && try_read("ukcy;") { +        return Some(CharRef { +            name: "ukcy;", +            characters: "\u{454}", +        }); +    } + +    if first_char == 'k' && try_read("appa;") { +        return Some(CharRef { +            name: "appa;", +            characters: "\u{3ba}", +        }); +    } + +    if first_char == 'l' && try_read("Aarr;") { +        return Some(CharRef { +            name: "Aarr;", +            characters: "\u{21da}", +        }); +    } + +    if first_char == 'l' && try_read("Barr;") { +        return Some(CharRef { +            name: "Barr;", +            characters: "\u{290e}", +        }); +    } + +    if first_char == 'l' && try_read("angd;") { +        return Some(CharRef { +            name: "angd;", +            characters: "\u{2991}", +        }); +    } + +    if first_char == 'l' && try_read("aquo;") { +        return Some(CharRef { +            name: "aquo;", +            characters: "\u{ab}", +        }); +    } + +    if first_char == 'l' && try_read("arrb;") { +        return Some(CharRef { +            name: "arrb;", +            characters: "\u{21e4}", +        }); +    } + +    if first_char == 'l' && try_read("ates;") { +        return Some(CharRef { +            name: "ates;", +            characters: "\u{2aad}\u{fe00}", +        }); +    } + +    if first_char == 'l' && try_read("barr;") { +        return Some(CharRef { +            name: "barr;", +            characters: "\u{290c}", +        }); +    } + +    if first_char == 'l' && try_read("bbrk;") { +        return Some(CharRef { +            name: "bbrk;", +            characters: "\u{2772}", +        }); +    } + +    if first_char == 'l' && try_read("brke;") { +        return Some(CharRef { +            name: "brke;", +            characters: "\u{298b}", +        }); +    } + +    if first_char == 'l' && try_read("ceil;") { +        return Some(CharRef { +            name: "ceil;", +            characters: "\u{2308}", +        }); +    } + +    if first_char == 'l' && try_read("dquo;") { +        return Some(CharRef { +            name: "dquo;", +            characters: "\u{201c}", +        }); +    } + +    if first_char == 'l' && try_read("escc;") { +        return Some(CharRef { +            name: "escc;", +            characters: "\u{2aa8}", +        }); +    } + +    if first_char == 'l' && try_read("hard;") { +        return Some(CharRef { +            name: "hard;", +            characters: "\u{21bd}", +        }); +    } + +    if first_char == 'l' && try_read("haru;") { +        return Some(CharRef { +            name: "haru;", +            characters: "\u{21bc}", +        }); +    } + +    if first_char == 'l' && try_read("hblk;") { +        return Some(CharRef { +            name: "hblk;", +            characters: "\u{2584}", +        }); +    } + +    if first_char == 'l' && try_read("larr;") { +        return Some(CharRef { +            name: "larr;", +            characters: "\u{21c7}", +        }); +    } + +    if first_char == 'l' && try_read("ltri;") { +        return Some(CharRef { +            name: "ltri;", +            characters: "\u{25fa}", +        }); +    } + +    if first_char == 'l' && try_read("neqq;") { +        return Some(CharRef { +            name: "neqq;", +            characters: "\u{2268}", +        }); +    } + +    if first_char == 'l' && try_read("nsim;") { +        return Some(CharRef { +            name: "nsim;", +            characters: "\u{22e6}", +        }); +    } + +    if first_char == 'l' && try_read("oang;") { +        return Some(CharRef { +            name: "oang;", +            characters: "\u{27ec}", +        }); +    } + +    if first_char == 'l' && try_read("oarr;") { +        return Some(CharRef { +            name: "oarr;", +            characters: "\u{21fd}", +        }); +    } + +    if first_char == 'l' && try_read("obrk;") { +        return Some(CharRef { +            name: "obrk;", +            characters: "\u{27e6}", +        }); +    } + +    if first_char == 'l' && try_read("opar;") { +        return Some(CharRef { +            name: "opar;", +            characters: "\u{2985}", +        }); +    } + +    if first_char == 'l' && try_read("rarr;") { +        return Some(CharRef { +            name: "rarr;", +            characters: "\u{21c6}", +        }); +    } + +    if first_char == 'l' && try_read("rhar;") { +        return Some(CharRef { +            name: "rhar;", +            characters: "\u{21cb}", +        }); +    } + +    if first_char == 'l' && try_read("rtri;") { +        return Some(CharRef { +            name: "rtri;", +            characters: "\u{22bf}", +        }); +    } + +    if first_char == 'l' && try_read("sime;") { +        return Some(CharRef { +            name: "sime;", +            characters: "\u{2a8d}", +        }); +    } + +    if first_char == 'l' && try_read("simg;") { +        return Some(CharRef { +            name: "simg;", +            characters: "\u{2a8f}", +        }); +    } + +    if first_char == 'l' && try_read("squo;") { +        return Some(CharRef { +            name: "squo;", +            characters: "\u{2018}", +        }); +    } + +    if first_char == 'l' && try_read("tcir;") { +        return Some(CharRef { +            name: "tcir;", +            characters: "\u{2a79}", +        }); +    } + +    if first_char == 'l' && try_read("tdot;") { +        return Some(CharRef { +            name: "tdot;", +            characters: "\u{22d6}", +        }); +    } + +    if first_char == 'l' && try_read("trie;") { +        return Some(CharRef { +            name: "trie;", +            characters: "\u{22b4}", +        }); +    } + +    if first_char == 'l' && try_read("trif;") { +        return Some(CharRef { +            name: "trif;", +            characters: "\u{25c2}", +        }); +    } + +    if first_char == 'm' && try_read("DDot;") { +        return Some(CharRef { +            name: "DDot;", +            characters: "\u{223a}", +        }); +    } + +    if first_char == 'm' && try_read("dash;") { +        return Some(CharRef { +            name: "dash;", +            characters: "\u{2014}", +        }); +    } + +    if first_char == 'm' && try_read("icro;") { +        return Some(CharRef { +            name: "icro;", +            characters: "\u{b5}", +        }); +    } + +    if first_char == 'm' && try_read("iddot") { +        return Some(CharRef { +            name: "iddot", +            characters: "\u{b7}", +        }); +    } + +    if first_char == 'm' && try_read("inus;") { +        return Some(CharRef { +            name: "inus;", +            characters: "\u{2212}", +        }); +    } + +    if first_char == 'm' && try_read("umap;") { +        return Some(CharRef { +            name: "umap;", +            characters: "\u{22b8}", +        }); +    } + +    if first_char == 'n' && try_read("abla;") { +        return Some(CharRef { +            name: "abla;", +            characters: "\u{2207}", +        }); +    } + +    if first_char == 'n' && try_read("apid;") { +        return Some(CharRef { +            name: "apid;", +            characters: "\u{224b}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("apos;") { +        return Some(CharRef { +            name: "apos;", +            characters: "\u{149}", +        }); +    } + +    if first_char == 'n' && try_read("atur;") { +        return Some(CharRef { +            name: "atur;", +            characters: "\u{266e}", +        }); +    } + +    if first_char == 'n' && try_read("bump;") { +        return Some(CharRef { +            name: "bump;", +            characters: "\u{224e}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("cong;") { +        return Some(CharRef { +            name: "cong;", +            characters: "\u{2247}", +        }); +    } + +    if first_char == 'n' && try_read("dash;") { +        return Some(CharRef { +            name: "dash;", +            characters: "\u{2013}", +        }); +    } + +    if first_char == 'n' && try_read("eArr;") { +        return Some(CharRef { +            name: "eArr;", +            characters: "\u{21d7}", +        }); +    } + +    if first_char == 'n' && try_read("earr;") { +        return Some(CharRef { +            name: "earr;", +            characters: "\u{2197}", +        }); +    } + +    if first_char == 'n' && try_read("edot;") { +        return Some(CharRef { +            name: "edot;", +            characters: "\u{2250}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("esim;") { +        return Some(CharRef { +            name: "esim;", +            characters: "\u{2242}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("geqq;") { +        return Some(CharRef { +            name: "geqq;", +            characters: "\u{2267}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("gsim;") { +        return Some(CharRef { +            name: "gsim;", +            characters: "\u{2275}", +        }); +    } + +    if first_char == 'n' && try_read("hArr;") { +        return Some(CharRef { +            name: "hArr;", +            characters: "\u{21ce}", +        }); +    } + +    if first_char == 'n' && try_read("harr;") { +        return Some(CharRef { +            name: "harr;", +            characters: "\u{21ae}", +        }); +    } + +    if first_char == 'n' && try_read("hpar;") { +        return Some(CharRef { +            name: "hpar;", +            characters: "\u{2af2}", +        }); +    } + +    if first_char == 'n' && try_read("lArr;") { +        return Some(CharRef { +            name: "lArr;", +            characters: "\u{21cd}", +        }); +    } + +    if first_char == 'n' && try_read("larr;") { +        return Some(CharRef { +            name: "larr;", +            characters: "\u{219a}", +        }); +    } + +    if first_char == 'n' && try_read("leqq;") { +        return Some(CharRef { +            name: "leqq;", +            characters: "\u{2266}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("less;") { +        return Some(CharRef { +            name: "less;", +            characters: "\u{226e}", +        }); +    } + +    if first_char == 'n' && try_read("lsim;") { +        return Some(CharRef { +            name: "lsim;", +            characters: "\u{2274}", +        }); +    } + +    if first_char == 'n' && try_read("ltri;") { +        return Some(CharRef { +            name: "ltri;", +            characters: "\u{22ea}", +        }); +    } + +    if first_char == 'n' && try_read("otin;") { +        return Some(CharRef { +            name: "otin;", +            characters: "\u{2209}", +        }); +    } + +    if first_char == 'n' && try_read("otni;") { +        return Some(CharRef { +            name: "otni;", +            characters: "\u{220c}", +        }); +    } + +    if first_char == 'n' && try_read("part;") { +        return Some(CharRef { +            name: "part;", +            characters: "\u{2202}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("prec;") { +        return Some(CharRef { +            name: "prec;", +            characters: "\u{2280}", +        }); +    } + +    if first_char == 'n' && try_read("rArr;") { +        return Some(CharRef { +            name: "rArr;", +            characters: "\u{21cf}", +        }); +    } + +    if first_char == 'n' && try_read("rarr;") { +        return Some(CharRef { +            name: "rarr;", +            characters: "\u{219b}", +        }); +    } + +    if first_char == 'n' && try_read("rtri;") { +        return Some(CharRef { +            name: "rtri;", +            characters: "\u{22eb}", +        }); +    } + +    if first_char == 'n' && try_read("sime;") { +        return Some(CharRef { +            name: "sime;", +            characters: "\u{2244}", +        }); +    } + +    if first_char == 'n' && try_read("smid;") { +        return Some(CharRef { +            name: "smid;", +            characters: "\u{2224}", +        }); +    } + +    if first_char == 'n' && try_read("spar;") { +        return Some(CharRef { +            name: "spar;", +            characters: "\u{2226}", +        }); +    } + +    if first_char == 'n' && try_read("subE;") { +        return Some(CharRef { +            name: "subE;", +            characters: "\u{2ac5}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("sube;") { +        return Some(CharRef { +            name: "sube;", +            characters: "\u{2288}", +        }); +    } + +    if first_char == 'n' && try_read("succ;") { +        return Some(CharRef { +            name: "succ;", +            characters: "\u{2281}", +        }); +    } + +    if first_char == 'n' && try_read("supE;") { +        return Some(CharRef { +            name: "supE;", +            characters: "\u{2ac6}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("supe;") { +        return Some(CharRef { +            name: "supe;", +            characters: "\u{2289}", +        }); +    } + +    if first_char == 'n' && try_read("tilde") { +        return Some(CharRef { +            name: "tilde", +            characters: "\u{f1}", +        }); +    } + +    if first_char == 'n' && try_read("umsp;") { +        return Some(CharRef { +            name: "umsp;", +            characters: "\u{2007}", +        }); +    } + +    if first_char == 'n' && try_read("vsim;") { +        return Some(CharRef { +            name: "vsim;", +            characters: "\u{223c}\u{20d2}", +        }); +    } + +    if first_char == 'n' && try_read("wArr;") { +        return Some(CharRef { +            name: "wArr;", +            characters: "\u{21d6}", +        }); +    } + +    if first_char == 'n' && try_read("warr;") { +        return Some(CharRef { +            name: "warr;", +            characters: "\u{2196}", +        }); +    } + +    if first_char == 'o' && try_read("acute") { +        return Some(CharRef { +            name: "acute", +            characters: "\u{f3}", +        }); +    } + +    if first_char == 'o' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{f4}", +        }); +    } + +    if first_char == 'o' && try_read("dash;") { +        return Some(CharRef { +            name: "dash;", +            characters: "\u{229d}", +        }); +    } + +    if first_char == 'o' && try_read("elig;") { +        return Some(CharRef { +            name: "elig;", +            characters: "\u{153}", +        }); +    } + +    if first_char == 'o' && try_read("fcir;") { +        return Some(CharRef { +            name: "fcir;", +            characters: "\u{29bf}", +        }); +    } + +    if first_char == 'o' && try_read("grave") { +        return Some(CharRef { +            name: "grave", +            characters: "\u{f2}", +        }); +    } + +    if first_char == 'o' && try_read("hbar;") { +        return Some(CharRef { +            name: "hbar;", +            characters: "\u{29b5}", +        }); +    } + +    if first_char == 'o' && try_read("larr;") { +        return Some(CharRef { +            name: "larr;", +            characters: "\u{21ba}", +        }); +    } + +    if first_char == 'o' && try_read("lcir;") { +        return Some(CharRef { +            name: "lcir;", +            characters: "\u{29be}", +        }); +    } + +    if first_char == 'o' && try_read("line;") { +        return Some(CharRef { +            name: "line;", +            characters: "\u{203e}", +        }); +    } + +    if first_char == 'o' && try_read("macr;") { +        return Some(CharRef { +            name: "macr;", +            characters: "\u{14d}", +        }); +    } + +    if first_char == 'o' && try_read("mega;") { +        return Some(CharRef { +            name: "mega;", +            characters: "\u{3c9}", +        }); +    } + +    if first_char == 'o' && try_read("perp;") { +        return Some(CharRef { +            name: "perp;", +            characters: "\u{29b9}", +        }); +    } + +    if first_char == 'o' && try_read("plus;") { +        return Some(CharRef { +            name: "plus;", +            characters: "\u{2295}", +        }); +    } + +    if first_char == 'o' && try_read("rarr;") { +        return Some(CharRef { +            name: "rarr;", +            characters: "\u{21bb}", +        }); +    } + +    if first_char == 'o' && try_read("rder;") { +        return Some(CharRef { +            name: "rder;", +            characters: "\u{2134}", +        }); +    } + +    if first_char == 'o' && try_read("slash") { +        return Some(CharRef { +            name: "slash", +            characters: "\u{f8}", +        }); +    } + +    if first_char == 'o' && try_read("tilde") { +        return Some(CharRef { +            name: "tilde", +            characters: "\u{f5}", +        }); +    } + +    if first_char == 'o' && try_read("vbar;") { +        return Some(CharRef { +            name: "vbar;", +            characters: "\u{233d}", +        }); +    } + +    if first_char == 'p' && try_read("arsl;") { +        return Some(CharRef { +            name: "arsl;", +            characters: "\u{2afd}", +        }); +    } + +    if first_char == 'p' && try_read("hone;") { +        return Some(CharRef { +            name: "hone;", +            characters: "\u{260e}", +        }); +    } + +    if first_char == 'p' && try_read("lusb;") { +        return Some(CharRef { +            name: "lusb;", +            characters: "\u{229e}", +        }); +    } + +    if first_char == 'p' && try_read("luse;") { +        return Some(CharRef { +            name: "luse;", +            characters: "\u{2a72}", +        }); +    } + +    if first_char == 'p' && try_read("lusmn") { +        return Some(CharRef { +            name: "lusmn", +            characters: "\u{b1}", +        }); +    } + +    if first_char == 'p' && try_read("ound;") { +        return Some(CharRef { +            name: "ound;", +            characters: "\u{a3}", +        }); +    } + +    if first_char == 'p' && try_read("rcue;") { +        return Some(CharRef { +            name: "rcue;", +            characters: "\u{227c}", +        }); +    } + +    if first_char == 'p' && try_read("rime;") { +        return Some(CharRef { +            name: "rime;", +            characters: "\u{2032}", +        }); +    } + +    if first_char == 'p' && try_read("rnap;") { +        return Some(CharRef { +            name: "rnap;", +            characters: "\u{2ab9}", +        }); +    } + +    if first_char == 'p' && try_read("rsim;") { +        return Some(CharRef { +            name: "rsim;", +            characters: "\u{227e}", +        }); +    } + +    if first_char == 'q' && try_read("uest;") { +        return Some(CharRef { +            name: "uest;", +            characters: "\u{3f}", +        }); +    } + +    if first_char == 'r' && try_read("Aarr;") { +        return Some(CharRef { +            name: "Aarr;", +            characters: "\u{21db}", +        }); +    } + +    if first_char == 'r' && try_read("Barr;") { +        return Some(CharRef { +            name: "Barr;", +            characters: "\u{290f}", +        }); +    } + +    if first_char == 'r' && try_read("adic;") { +        return Some(CharRef { +            name: "adic;", +            characters: "\u{221a}", +        }); +    } + +    if first_char == 'r' && try_read("angd;") { +        return Some(CharRef { +            name: "angd;", +            characters: "\u{2992}", +        }); +    } + +    if first_char == 'r' && try_read("ange;") { +        return Some(CharRef { +            name: "ange;", +            characters: "\u{29a5}", +        }); +    } + +    if first_char == 'r' && try_read("aquo;") { +        return Some(CharRef { +            name: "aquo;", +            characters: "\u{bb}", +        }); +    } + +    if first_char == 'r' && try_read("arrb;") { +        return Some(CharRef { +            name: "arrb;", +            characters: "\u{21e5}", +        }); +    } + +    if first_char == 'r' && try_read("arrc;") { +        return Some(CharRef { +            name: "arrc;", +            characters: "\u{2933}", +        }); +    } + +    if first_char == 'r' && try_read("arrw;") { +        return Some(CharRef { +            name: "arrw;", +            characters: "\u{219d}", +        }); +    } + +    if first_char == 'r' && try_read("atio;") { +        return Some(CharRef { +            name: "atio;", +            characters: "\u{2236}", +        }); +    } + +    if first_char == 'r' && try_read("barr;") { +        return Some(CharRef { +            name: "barr;", +            characters: "\u{290d}", +        }); +    } + +    if first_char == 'r' && try_read("bbrk;") { +        return Some(CharRef { +            name: "bbrk;", +            characters: "\u{2773}", +        }); +    } + +    if first_char == 'r' && try_read("brke;") { +        return Some(CharRef { +            name: "brke;", +            characters: "\u{298c}", +        }); +    } + +    if first_char == 'r' && try_read("ceil;") { +        return Some(CharRef { +            name: "ceil;", +            characters: "\u{2309}", +        }); +    } + +    if first_char == 'r' && try_read("dquo;") { +        return Some(CharRef { +            name: "dquo;", +            characters: "\u{201d}", +        }); +    } + +    if first_char == 'r' && try_read("eals;") { +        return Some(CharRef { +            name: "eals;", +            characters: "\u{211d}", +        }); +    } + +    if first_char == 'r' && try_read("hard;") { +        return Some(CharRef { +            name: "hard;", +            characters: "\u{21c1}", +        }); +    } + +    if first_char == 'r' && try_read("haru;") { +        return Some(CharRef { +            name: "haru;", +            characters: "\u{21c0}", +        }); +    } + +    if first_char == 'r' && try_read("larr;") { +        return Some(CharRef { +            name: "larr;", +            characters: "\u{21c4}", +        }); +    } + +    if first_char == 'r' && try_read("lhar;") { +        return Some(CharRef { +            name: "lhar;", +            characters: "\u{21cc}", +        }); +    } + +    if first_char == 'r' && try_read("nmid;") { +        return Some(CharRef { +            name: "nmid;", +            characters: "\u{2aee}", +        }); +    } + +    if first_char == 'r' && try_read("oang;") { +        return Some(CharRef { +            name: "oang;", +            characters: "\u{27ed}", +        }); +    } + +    if first_char == 'r' && try_read("oarr;") { +        return Some(CharRef { +            name: "oarr;", +            characters: "\u{21fe}", +        }); +    } + +    if first_char == 'r' && try_read("obrk;") { +        return Some(CharRef { +            name: "obrk;", +            characters: "\u{27e7}", +        }); +    } + +    if first_char == 'r' && try_read("opar;") { +        return Some(CharRef { +            name: "opar;", +            characters: "\u{2986}", +        }); +    } + +    if first_char == 'r' && try_read("rarr;") { +        return Some(CharRef { +            name: "rarr;", +            characters: "\u{21c9}", +        }); +    } + +    if first_char == 'r' && try_read("squo;") { +        return Some(CharRef { +            name: "squo;", +            characters: "\u{2019}", +        }); +    } + +    if first_char == 'r' && try_read("trie;") { +        return Some(CharRef { +            name: "trie;", +            characters: "\u{22b5}", +        }); +    } + +    if first_char == 'r' && try_read("trif;") { +        return Some(CharRef { +            name: "trif;", +            characters: "\u{25b8}", +        }); +    } + +    if first_char == 's' && try_read("bquo;") { +        return Some(CharRef { +            name: "bquo;", +            characters: "\u{201a}", +        }); +    } + +    if first_char == 's' && try_read("ccue;") { +        return Some(CharRef { +            name: "ccue;", +            characters: "\u{227d}", +        }); +    } + +    if first_char == 's' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{15d}", +        }); +    } + +    if first_char == 's' && try_read("cnap;") { +        return Some(CharRef { +            name: "cnap;", +            characters: "\u{2aba}", +        }); +    } + +    if first_char == 's' && try_read("csim;") { +        return Some(CharRef { +            name: "csim;", +            characters: "\u{227f}", +        }); +    } + +    if first_char == 's' && try_read("dotb;") { +        return Some(CharRef { +            name: "dotb;", +            characters: "\u{22a1}", +        }); +    } + +    if first_char == 's' && try_read("dote;") { +        return Some(CharRef { +            name: "dote;", +            characters: "\u{2a66}", +        }); +    } + +    if first_char == 's' && try_read("eArr;") { +        return Some(CharRef { +            name: "eArr;", +            characters: "\u{21d8}", +        }); +    } + +    if first_char == 's' && try_read("earr;") { +        return Some(CharRef { +            name: "earr;", +            characters: "\u{2198}", +        }); +    } + +    if first_char == 's' && try_read("etmn;") { +        return Some(CharRef { +            name: "etmn;", +            characters: "\u{2216}", +        }); +    } + +    if first_char == 's' && try_read("harp;") { +        return Some(CharRef { +            name: "harp;", +            characters: "\u{266f}", +        }); +    } + +    if first_char == 's' && try_read("igma;") { +        return Some(CharRef { +            name: "igma;", +            characters: "\u{3c3}", +        }); +    } + +    if first_char == 's' && try_read("imeq;") { +        return Some(CharRef { +            name: "imeq;", +            characters: "\u{2243}", +        }); +    } + +    if first_char == 's' && try_read("imgE;") { +        return Some(CharRef { +            name: "imgE;", +            characters: "\u{2aa0}", +        }); +    } + +    if first_char == 's' && try_read("imlE;") { +        return Some(CharRef { +            name: "imlE;", +            characters: "\u{2a9f}", +        }); +    } + +    if first_char == 's' && try_read("imne;") { +        return Some(CharRef { +            name: "imne;", +            characters: "\u{2246}", +        }); +    } + +    if first_char == 's' && try_read("larr;") { +        return Some(CharRef { +            name: "larr;", +            characters: "\u{2190}", +        }); +    } + +    if first_char == 's' && try_read("mile;") { +        return Some(CharRef { +            name: "mile;", +            characters: "\u{2323}", +        }); +    } + +    if first_char == 's' && try_read("mtes;") { +        return Some(CharRef { +            name: "mtes;", +            characters: "\u{2aac}\u{fe00}", +        }); +    } + +    if first_char == 's' && try_read("qcap;") { +        return Some(CharRef { +            name: "qcap;", +            characters: "\u{2293}", +        }); +    } + +    if first_char == 's' && try_read("qcup;") { +        return Some(CharRef { +            name: "qcup;", +            characters: "\u{2294}", +        }); +    } + +    if first_char == 's' && try_read("qsub;") { +        return Some(CharRef { +            name: "qsub;", +            characters: "\u{228f}", +        }); +    } + +    if first_char == 's' && try_read("qsup;") { +        return Some(CharRef { +            name: "qsup;", +            characters: "\u{2290}", +        }); +    } + +    if first_char == 's' && try_read("rarr;") { +        return Some(CharRef { +            name: "rarr;", +            characters: "\u{2192}", +        }); +    } + +    if first_char == 's' && try_read("tarf;") { +        return Some(CharRef { +            name: "tarf;", +            characters: "\u{2605}", +        }); +    } + +    if first_char == 's' && try_read("trns;") { +        return Some(CharRef { +            name: "trns;", +            characters: "\u{af}", +        }); +    } + +    if first_char == 's' && try_read("ubnE;") { +        return Some(CharRef { +            name: "ubnE;", +            characters: "\u{2acb}", +        }); +    } + +    if first_char == 's' && try_read("ubne;") { +        return Some(CharRef { +            name: "ubne;", +            characters: "\u{228a}", +        }); +    } + +    if first_char == 's' && try_read("upnE;") { +        return Some(CharRef { +            name: "upnE;", +            characters: "\u{2acc}", +        }); +    } + +    if first_char == 's' && try_read("upne;") { +        return Some(CharRef { +            name: "upne;", +            characters: "\u{228b}", +        }); +    } + +    if first_char == 's' && try_read("wArr;") { +        return Some(CharRef { +            name: "wArr;", +            characters: "\u{21d9}", +        }); +    } + +    if first_char == 's' && try_read("warr;") { +        return Some(CharRef { +            name: "warr;", +            characters: "\u{2199}", +        }); +    } + +    if first_char == 's' && try_read("zlig;") { +        return Some(CharRef { +            name: "zlig;", +            characters: "\u{df}", +        }); +    } + +    if first_char == 't' && try_read("heta;") { +        return Some(CharRef { +            name: "heta;", +            characters: "\u{3b8}", +        }); +    } + +    if first_char == 't' && try_read("hkap;") { +        return Some(CharRef { +            name: "hkap;", +            characters: "\u{2248}", +        }); +    } + +    if first_char == 't' && try_read("horn;") { +        return Some(CharRef { +            name: "horn;", +            characters: "\u{fe}", +        }); +    } + +    if first_char == 't' && try_read("ilde;") { +        return Some(CharRef { +            name: "ilde;", +            characters: "\u{2dc}", +        }); +    } + +    if first_char == 't' && try_read("imes;") { +        return Some(CharRef { +            name: "imes;", +            characters: "\u{d7}", +        }); +    } + +    if first_char == 't' && try_read("rade;") { +        return Some(CharRef { +            name: "rade;", +            characters: "\u{2122}", +        }); +    } + +    if first_char == 't' && try_read("risb;") { +        return Some(CharRef { +            name: "risb;", +            characters: "\u{29cd}", +        }); +    } + +    if first_char == 't' && try_read("shcy;") { +        return Some(CharRef { +            name: "shcy;", +            characters: "\u{45b}", +        }); +    } + +    if first_char == 't' && try_read("wixt;") { +        return Some(CharRef { +            name: "wixt;", +            characters: "\u{226c}", +        }); +    } + +    if first_char == 'u' && try_read("acute") { +        return Some(CharRef { +            name: "acute", +            characters: "\u{fa}", +        }); +    } + +    if first_char == 'u' && try_read("brcy;") { +        return Some(CharRef { +            name: "brcy;", +            characters: "\u{45e}", +        }); +    } + +    if first_char == 'u' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{fb}", +        }); +    } + +    if first_char == 'u' && try_read("darr;") { +        return Some(CharRef { +            name: "darr;", +            characters: "\u{21c5}", +        }); +    } + +    if first_char == 'u' && try_read("dhar;") { +        return Some(CharRef { +            name: "dhar;", +            characters: "\u{296e}", +        }); +    } + +    if first_char == 'u' && try_read("grave") { +        return Some(CharRef { +            name: "grave", +            characters: "\u{f9}", +        }); +    } + +    if first_char == 'u' && try_read("harl;") { +        return Some(CharRef { +            name: "harl;", +            characters: "\u{21bf}", +        }); +    } + +    if first_char == 'u' && try_read("harr;") { +        return Some(CharRef { +            name: "harr;", +            characters: "\u{21be}", +        }); +    } + +    if first_char == 'u' && try_read("hblk;") { +        return Some(CharRef { +            name: "hblk;", +            characters: "\u{2580}", +        }); +    } + +    if first_char == 'u' && try_read("ltri;") { +        return Some(CharRef { +            name: "ltri;", +            characters: "\u{25f8}", +        }); +    } + +    if first_char == 'u' && try_read("macr;") { +        return Some(CharRef { +            name: "macr;", +            characters: "\u{16b}", +        }); +    } + +    if first_char == 'u' && try_read("ogon;") { +        return Some(CharRef { +            name: "ogon;", +            characters: "\u{173}", +        }); +    } + +    if first_char == 'u' && try_read("plus;") { +        return Some(CharRef { +            name: "plus;", +            characters: "\u{228e}", +        }); +    } + +    if first_char == 'u' && try_read("psih;") { +        return Some(CharRef { +            name: "psih;", +            characters: "\u{3d2}", +        }); +    } + +    if first_char == 'u' && try_read("ring;") { +        return Some(CharRef { +            name: "ring;", +            characters: "\u{16f}", +        }); +    } + +    if first_char == 'u' && try_read("rtri;") { +        return Some(CharRef { +            name: "rtri;", +            characters: "\u{25f9}", +        }); +    } + +    if first_char == 'u' && try_read("tdot;") { +        return Some(CharRef { +            name: "tdot;", +            characters: "\u{22f0}", +        }); +    } + +    if first_char == 'u' && try_read("trif;") { +        return Some(CharRef { +            name: "trif;", +            characters: "\u{25b4}", +        }); +    } + +    if first_char == 'u' && try_read("uarr;") { +        return Some(CharRef { +            name: "uarr;", +            characters: "\u{21c8}", +        }); +    } + +    if first_char == 'v' && try_read("Barv;") { +        return Some(CharRef { +            name: "Barv;", +            characters: "\u{2ae9}", +        }); +    } + +    if first_char == 'v' && try_read("Dash;") { +        return Some(CharRef { +            name: "Dash;", +            characters: "\u{22a8}", +        }); +    } + +    if first_char == 'v' && try_read("arpi;") { +        return Some(CharRef { +            name: "arpi;", +            characters: "\u{3d6}", +        }); +    } + +    if first_char == 'v' && try_read("dash;") { +        return Some(CharRef { +            name: "dash;", +            characters: "\u{22a2}", +        }); +    } + +    if first_char == 'v' && try_read("eeeq;") { +        return Some(CharRef { +            name: "eeeq;", +            characters: "\u{225a}", +        }); +    } + +    if first_char == 'v' && try_read("ltri;") { +        return Some(CharRef { +            name: "ltri;", +            characters: "\u{22b2}", +        }); +    } + +    if first_char == 'v' && try_read("nsub;") { +        return Some(CharRef { +            name: "nsub;", +            characters: "\u{2282}\u{20d2}", +        }); +    } + +    if first_char == 'v' && try_read("nsup;") { +        return Some(CharRef { +            name: "nsup;", +            characters: "\u{2283}\u{20d2}", +        }); +    } + +    if first_char == 'v' && try_read("prop;") { +        return Some(CharRef { +            name: "prop;", +            characters: "\u{221d}", +        }); +    } + +    if first_char == 'v' && try_read("rtri;") { +        return Some(CharRef { +            name: "rtri;", +            characters: "\u{22b3}", +        }); +    } + +    if first_char == 'w' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{175}", +        }); +    } + +    if first_char == 'w' && try_read("edge;") { +        return Some(CharRef { +            name: "edge;", +            characters: "\u{2227}", +        }); +    } + +    if first_char == 'x' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{25ef}", +        }); +    } + +    if first_char == 'x' && try_read("dtri;") { +        return Some(CharRef { +            name: "dtri;", +            characters: "\u{25bd}", +        }); +    } + +    if first_char == 'x' && try_read("hArr;") { +        return Some(CharRef { +            name: "hArr;", +            characters: "\u{27fa}", +        }); +    } + +    if first_char == 'x' && try_read("harr;") { +        return Some(CharRef { +            name: "harr;", +            characters: "\u{27f7}", +        }); +    } + +    if first_char == 'x' && try_read("lArr;") { +        return Some(CharRef { +            name: "lArr;", +            characters: "\u{27f8}", +        }); +    } + +    if first_char == 'x' && try_read("larr;") { +        return Some(CharRef { +            name: "larr;", +            characters: "\u{27f5}", +        }); +    } + +    if first_char == 'x' && try_read("odot;") { +        return Some(CharRef { +            name: "odot;", +            characters: "\u{2a00}", +        }); +    } + +    if first_char == 'x' && try_read("rArr;") { +        return Some(CharRef { +            name: "rArr;", +            characters: "\u{27f9}", +        }); +    } + +    if first_char == 'x' && try_read("rarr;") { +        return Some(CharRef { +            name: "rarr;", +            characters: "\u{27f6}", +        }); +    } + +    if first_char == 'x' && try_read("utri;") { +        return Some(CharRef { +            name: "utri;", +            characters: "\u{25b3}", +        }); +    } + +    if first_char == 'y' && try_read("acute") { +        return Some(CharRef { +            name: "acute", +            characters: "\u{fd}", +        }); +    } + +    if first_char == 'y' && try_read("circ;") { +        return Some(CharRef { +            name: "circ;", +            characters: "\u{177}", +        }); +    } + +    if first_char == 'A' && try_read("Elig") { +        return Some(CharRef { +            name: "Elig", +            characters: "\u{c6}", +        }); +    } + +    if first_char == 'A' && try_read("circ") { +        return Some(CharRef { +            name: "circ", +            characters: "\u{c2}", +        }); +    } + +    if first_char == 'A' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d538}", +        }); +    } + +    if first_char == 'A' && try_read("ring") { +        return Some(CharRef { +            name: "ring", +            characters: "\u{c5}", +        }); +    } + +    if first_char == 'A' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d49c}", +        }); +    } + +    if first_char == 'A' && try_read("uml;") { +        return Some(CharRef { +            name: "uml;", +            characters: "\u{c4}", +        }); +    } + +    if first_char == 'B' && try_read("arv;") { +        return Some(CharRef { +            name: "arv;", +            characters: "\u{2ae7}", +        }); +    } + +    if first_char == 'B' && try_read("eta;") { +        return Some(CharRef { +            name: "eta;", +            characters: "\u{392}", +        }); +    } + +    if first_char == 'B' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d539}", +        }); +    } + +    if first_char == 'B' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{212c}", +        }); +    } + +    if first_char == 'C' && try_read("Hcy;") { +        return Some(CharRef { +            name: "Hcy;", +            characters: "\u{427}", +        }); +    } + +    if first_char == 'C' && try_read("OPY;") { +        return Some(CharRef { +            name: "OPY;", +            characters: "\u{a9}", +        }); +    } + +    if first_char == 'C' && try_read("dot;") { +        return Some(CharRef { +            name: "dot;", +            characters: "\u{10a}", +        }); +    } + +    if first_char == 'C' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{2102}", +        }); +    } + +    if first_char == 'C' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d49e}", +        }); +    } + +    if first_char == 'D' && try_read("Jcy;") { +        return Some(CharRef { +            name: "Jcy;", +            characters: "\u{402}", +        }); +    } + +    if first_char == 'D' && try_read("Scy;") { +        return Some(CharRef { +            name: "Scy;", +            characters: "\u{405}", +        }); +    } + +    if first_char == 'D' && try_read("Zcy;") { +        return Some(CharRef { +            name: "Zcy;", +            characters: "\u{40f}", +        }); +    } + +    if first_char == 'D' && try_read("arr;") { +        return Some(CharRef { +            name: "arr;", +            characters: "\u{21a1}", +        }); +    } + +    if first_char == 'D' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d53b}", +        }); +    } + +    if first_char == 'D' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d49f}", +        }); +    } + +    if first_char == 'E' && try_read("circ") { +        return Some(CharRef { +            name: "circ", +            characters: "\u{ca}", +        }); +    } + +    if first_char == 'E' && try_read("dot;") { +        return Some(CharRef { +            name: "dot;", +            characters: "\u{116}", +        }); +    } + +    if first_char == 'E' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d53c}", +        }); +    } + +    if first_char == 'E' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{2130}", +        }); +    } + +    if first_char == 'E' && try_read("sim;") { +        return Some(CharRef { +            name: "sim;", +            characters: "\u{2a73}", +        }); +    } + +    if first_char == 'E' && try_read("uml;") { +        return Some(CharRef { +            name: "uml;", +            characters: "\u{cb}", +        }); +    } + +    if first_char == 'F' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d53d}", +        }); +    } + +    if first_char == 'F' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{2131}", +        }); +    } + +    if first_char == 'G' && try_read("Jcy;") { +        return Some(CharRef { +            name: "Jcy;", +            characters: "\u{403}", +        }); +    } + +    if first_char == 'G' && try_read("dot;") { +        return Some(CharRef { +            name: "dot;", +            characters: "\u{120}", +        }); +    } + +    if first_char == 'G' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d53e}", +        }); +    } + +    if first_char == 'G' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4a2}", +        }); +    } + +    if first_char == 'H' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{210d}", +        }); +    } + +    if first_char == 'H' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{210b}", +        }); +    } + +    if first_char == 'I' && try_read("Ecy;") { +        return Some(CharRef { +            name: "Ecy;", +            characters: "\u{415}", +        }); +    } + +    if first_char == 'I' && try_read("Ocy;") { +        return Some(CharRef { +            name: "Ocy;", +            characters: "\u{401}", +        }); +    } + +    if first_char == 'I' && try_read("circ") { +        return Some(CharRef { +            name: "circ", +            characters: "\u{ce}", +        }); +    } + +    if first_char == 'I' && try_read("dot;") { +        return Some(CharRef { +            name: "dot;", +            characters: "\u{130}", +        }); +    } + +    if first_char == 'I' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d540}", +        }); +    } + +    if first_char == 'I' && try_read("ota;") { +        return Some(CharRef { +            name: "ota;", +            characters: "\u{399}", +        }); +    } + +    if first_char == 'I' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{2110}", +        }); +    } + +    if first_char == 'I' && try_read("uml;") { +        return Some(CharRef { +            name: "uml;", +            characters: "\u{cf}", +        }); +    } + +    if first_char == 'J' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d541}", +        }); +    } + +    if first_char == 'J' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4a5}", +        }); +    } + +    if first_char == 'K' && try_read("Hcy;") { +        return Some(CharRef { +            name: "Hcy;", +            characters: "\u{425}", +        }); +    } + +    if first_char == 'K' && try_read("Jcy;") { +        return Some(CharRef { +            name: "Jcy;", +            characters: "\u{40c}", +        }); +    } + +    if first_char == 'K' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d542}", +        }); +    } + +    if first_char == 'K' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4a6}", +        }); +    } + +    if first_char == 'L' && try_read("Jcy;") { +        return Some(CharRef { +            name: "Jcy;", +            characters: "\u{409}", +        }); +    } + +    if first_char == 'L' && try_read("ang;") { +        return Some(CharRef { +            name: "ang;", +            characters: "\u{27ea}", +        }); +    } + +    if first_char == 'L' && try_read("arr;") { +        return Some(CharRef { +            name: "arr;", +            characters: "\u{219e}", +        }); +    } + +    if first_char == 'L' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d543}", +        }); +    } + +    if first_char == 'L' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{2112}", +        }); +    } + +    if first_char == 'M' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d544}", +        }); +    } + +    if first_char == 'M' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{2133}", +        }); +    } + +    if first_char == 'N' && try_read("Jcy;") { +        return Some(CharRef { +            name: "Jcy;", +            characters: "\u{40a}", +        }); +    } + +    if first_char == 'N' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{2115}", +        }); +    } + +    if first_char == 'N' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4a9}", +        }); +    } + +    if first_char == 'O' && try_read("circ") { +        return Some(CharRef { +            name: "circ", +            characters: "\u{d4}", +        }); +    } + +    if first_char == 'O' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d546}", +        }); +    } + +    if first_char == 'O' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4aa}", +        }); +    } + +    if first_char == 'O' && try_read("uml;") { +        return Some(CharRef { +            name: "uml;", +            characters: "\u{d6}", +        }); +    } + +    if first_char == 'P' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{2119}", +        }); +    } + +    if first_char == 'P' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4ab}", +        }); +    } + +    if first_char == 'Q' && try_read("UOT;") { +        return Some(CharRef { +            name: "UOT;", +            characters: "\u{22}", +        }); +    } + +    if first_char == 'Q' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{211a}", +        }); +    } + +    if first_char == 'Q' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4ac}", +        }); +    } + +    if first_char == 'R' && try_read("ang;") { +        return Some(CharRef { +            name: "ang;", +            characters: "\u{27eb}", +        }); +    } + +    if first_char == 'R' && try_read("arr;") { +        return Some(CharRef { +            name: "arr;", +            characters: "\u{21a0}", +        }); +    } + +    if first_char == 'R' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{211d}", +        }); +    } + +    if first_char == 'R' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{211b}", +        }); +    } + +    if first_char == 'S' && try_read("Hcy;") { +        return Some(CharRef { +            name: "Hcy;", +            characters: "\u{428}", +        }); +    } + +    if first_char == 'S' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d54a}", +        }); +    } + +    if first_char == 'S' && try_read("qrt;") { +        return Some(CharRef { +            name: "qrt;", +            characters: "\u{221a}", +        }); +    } + +    if first_char == 'S' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4ae}", +        }); +    } + +    if first_char == 'S' && try_read("tar;") { +        return Some(CharRef { +            name: "tar;", +            characters: "\u{22c6}", +        }); +    } + +    if first_char == 'T' && try_read("HORN") { +        return Some(CharRef { +            name: "HORN", +            characters: "\u{de}", +        }); +    } + +    if first_char == 'T' && try_read("Scy;") { +        return Some(CharRef { +            name: "Scy;", +            characters: "\u{426}", +        }); +    } + +    if first_char == 'T' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d54b}", +        }); +    } + +    if first_char == 'T' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4af}", +        }); +    } + +    if first_char == 'U' && try_read("arr;") { +        return Some(CharRef { +            name: "arr;", +            characters: "\u{219f}", +        }); +    } + +    if first_char == 'U' && try_read("circ") { +        return Some(CharRef { +            name: "circ", +            characters: "\u{db}", +        }); +    } + +    if first_char == 'U' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d54c}", +        }); +    } + +    if first_char == 'U' && try_read("psi;") { +        return Some(CharRef { +            name: "psi;", +            characters: "\u{3d2}", +        }); +    } + +    if first_char == 'U' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4b0}", +        }); +    } + +    if first_char == 'U' && try_read("uml;") { +        return Some(CharRef { +            name: "uml;", +            characters: "\u{dc}", +        }); +    } + +    if first_char == 'V' && try_read("bar;") { +        return Some(CharRef { +            name: "bar;", +            characters: "\u{2aeb}", +        }); +    } + +    if first_char == 'V' && try_read("ert;") { +        return Some(CharRef { +            name: "ert;", +            characters: "\u{2016}", +        }); +    } + +    if first_char == 'V' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d54d}", +        }); +    } + +    if first_char == 'V' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4b1}", +        }); +    } + +    if first_char == 'W' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d54e}", +        }); +    } + +    if first_char == 'W' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4b2}", +        }); +    } + +    if first_char == 'X' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d54f}", +        }); +    } + +    if first_char == 'X' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4b3}", +        }); +    } + +    if first_char == 'Y' && try_read("Acy;") { +        return Some(CharRef { +            name: "Acy;", +            characters: "\u{42f}", +        }); +    } + +    if first_char == 'Y' && try_read("Icy;") { +        return Some(CharRef { +            name: "Icy;", +            characters: "\u{407}", +        }); +    } + +    if first_char == 'Y' && try_read("Ucy;") { +        return Some(CharRef { +            name: "Ucy;", +            characters: "\u{42e}", +        }); +    } + +    if first_char == 'Y' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d550}", +        }); +    } + +    if first_char == 'Y' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4b4}", +        }); +    } + +    if first_char == 'Y' && try_read("uml;") { +        return Some(CharRef { +            name: "uml;", +            characters: "\u{178}", +        }); +    } + +    if first_char == 'Z' && try_read("Hcy;") { +        return Some(CharRef { +            name: "Hcy;", +            characters: "\u{416}", +        }); +    } + +    if first_char == 'Z' && try_read("dot;") { +        return Some(CharRef { +            name: "dot;", +            characters: "\u{17b}", +        }); +    } + +    if first_char == 'Z' && try_read("eta;") { +        return Some(CharRef { +            name: "eta;", +            characters: "\u{396}", +        }); +    } + +    if first_char == 'Z' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{2124}", +        }); +    } + +    if first_char == 'Z' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4b5}", +        }); +    } + +    if first_char == 'a' && try_read("circ") { +        return Some(CharRef { +            name: "circ", +            characters: "\u{e2}", +        }); +    } + +    if first_char == 'a' && try_read("cute") { +        return Some(CharRef { +            name: "cute", +            characters: "\u{b4}", +        }); +    } + +    if first_char == 'a' && try_read("elig") { +        return Some(CharRef { +            name: "elig", +            characters: "\u{e6}", +        }); +    } + +    if first_char == 'a' && try_read("ndd;") { +        return Some(CharRef { +            name: "ndd;", +            characters: "\u{2a5c}", +        }); +    } + +    if first_char == 'a' && try_read("ndv;") { +        return Some(CharRef { +            name: "ndv;", +            characters: "\u{2a5a}", +        }); +    } + +    if first_char == 'a' && try_read("nge;") { +        return Some(CharRef { +            name: "nge;", +            characters: "\u{29a4}", +        }); +    } + +    if first_char == 'a' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d552}", +        }); +    } + +    if first_char == 'a' && try_read("pid;") { +        return Some(CharRef { +            name: "pid;", +            characters: "\u{224b}", +        }); +    } + +    if first_char == 'a' && try_read("pos;") { +        return Some(CharRef { +            name: "pos;", +            characters: "\u{27}", +        }); +    } + +    if first_char == 'a' && try_read("ring") { +        return Some(CharRef { +            name: "ring", +            characters: "\u{e5}", +        }); +    } + +    if first_char == 'a' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4b6}", +        }); +    } + +    if first_char == 'a' && try_read("uml;") { +        return Some(CharRef { +            name: "uml;", +            characters: "\u{e4}", +        }); +    } + +    if first_char == 'b' && try_read("Not;") { +        return Some(CharRef { +            name: "Not;", +            characters: "\u{2aed}", +        }); +    } + +    if first_char == 'b' && try_read("brk;") { +        return Some(CharRef { +            name: "brk;", +            characters: "\u{23b5}", +        }); +    } + +    if first_char == 'b' && try_read("eta;") { +        return Some(CharRef { +            name: "eta;", +            characters: "\u{3b2}", +        }); +    } + +    if first_char == 'b' && try_read("eth;") { +        return Some(CharRef { +            name: "eth;", +            characters: "\u{2136}", +        }); +    } + +    if first_char == 'b' && try_read("not;") { +        return Some(CharRef { +            name: "not;", +            characters: "\u{2310}", +        }); +    } + +    if first_char == 'b' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d553}", +        }); +    } + +    if first_char == 'b' && try_read("oxH;") { +        return Some(CharRef { +            name: "oxH;", +            characters: "\u{2550}", +        }); +    } + +    if first_char == 'b' && try_read("oxV;") { +        return Some(CharRef { +            name: "oxV;", +            characters: "\u{2551}", +        }); +    } + +    if first_char == 'b' && try_read("oxh;") { +        return Some(CharRef { +            name: "oxh;", +            characters: "\u{2500}", +        }); +    } + +    if first_char == 'b' && try_read("oxv;") { +        return Some(CharRef { +            name: "oxv;", +            characters: "\u{2502}", +        }); +    } + +    if first_char == 'b' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4b7}", +        }); +    } + +    if first_char == 'b' && try_read("sim;") { +        return Some(CharRef { +            name: "sim;", +            characters: "\u{223d}", +        }); +    } + +    if first_char == 'b' && try_read("sol;") { +        return Some(CharRef { +            name: "sol;", +            characters: "\u{5c}", +        }); +    } + +    if first_char == 'b' && try_read("ull;") { +        return Some(CharRef { +            name: "ull;", +            characters: "\u{2022}", +        }); +    } + +    if first_char == 'b' && try_read("ump;") { +        return Some(CharRef { +            name: "ump;", +            characters: "\u{224e}", +        }); +    } + +    if first_char == 'c' && try_read("aps;") { +        return Some(CharRef { +            name: "aps;", +            characters: "\u{2229}\u{fe00}", +        }); +    } + +    if first_char == 'c' && try_read("dot;") { +        return Some(CharRef { +            name: "dot;", +            characters: "\u{10b}", +        }); +    } + +    if first_char == 'c' && try_read("edil") { +        return Some(CharRef { +            name: "edil", +            characters: "\u{b8}", +        }); +    } + +    if first_char == 'c' && try_read("ent;") { +        return Some(CharRef { +            name: "ent;", +            characters: "\u{a2}", +        }); +    } + +    if first_char == 'c' && try_read("hcy;") { +        return Some(CharRef { +            name: "hcy;", +            characters: "\u{447}", +        }); +    } + +    if first_char == 'c' && try_read("irE;") { +        return Some(CharRef { +            name: "irE;", +            characters: "\u{29c3}", +        }); +    } + +    if first_char == 'c' && try_read("irc;") { +        return Some(CharRef { +            name: "irc;", +            characters: "\u{2c6}", +        }); +    } + +    if first_char == 'c' && try_read("ire;") { +        return Some(CharRef { +            name: "ire;", +            characters: "\u{2257}", +        }); +    } + +    if first_char == 'c' && try_read("omp;") { +        return Some(CharRef { +            name: "omp;", +            characters: "\u{2201}", +        }); +    } + +    if first_char == 'c' && try_read("ong;") { +        return Some(CharRef { +            name: "ong;", +            characters: "\u{2245}", +        }); +    } + +    if first_char == 'c' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d554}", +        }); +    } + +    if first_char == 'c' && try_read("opy;") { +        return Some(CharRef { +            name: "opy;", +            characters: "\u{a9}", +        }); +    } + +    if first_char == 'c' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4b8}", +        }); +    } + +    if first_char == 'c' && try_read("sub;") { +        return Some(CharRef { +            name: "sub;", +            characters: "\u{2acf}", +        }); +    } + +    if first_char == 'c' && try_read("sup;") { +        return Some(CharRef { +            name: "sup;", +            characters: "\u{2ad0}", +        }); +    } + +    if first_char == 'c' && try_read("ups;") { +        return Some(CharRef { +            name: "ups;", +            characters: "\u{222a}\u{fe00}", +        }); +    } + +    if first_char == 'd' && try_read("Arr;") { +        return Some(CharRef { +            name: "Arr;", +            characters: "\u{21d3}", +        }); +    } + +    if first_char == 'd' && try_read("Har;") { +        return Some(CharRef { +            name: "Har;", +            characters: "\u{2965}", +        }); +    } + +    if first_char == 'd' && try_read("arr;") { +        return Some(CharRef { +            name: "arr;", +            characters: "\u{2193}", +        }); +    } + +    if first_char == 'd' && try_read("ash;") { +        return Some(CharRef { +            name: "ash;", +            characters: "\u{2010}", +        }); +    } + +    if first_char == 'd' && try_read("iam;") { +        return Some(CharRef { +            name: "iam;", +            characters: "\u{22c4}", +        }); +    } + +    if first_char == 'd' && try_read("jcy;") { +        return Some(CharRef { +            name: "jcy;", +            characters: "\u{452}", +        }); +    } + +    if first_char == 'd' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d555}", +        }); +    } + +    if first_char == 'd' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4b9}", +        }); +    } + +    if first_char == 'd' && try_read("scy;") { +        return Some(CharRef { +            name: "scy;", +            characters: "\u{455}", +        }); +    } + +    if first_char == 'd' && try_read("sol;") { +        return Some(CharRef { +            name: "sol;", +            characters: "\u{29f6}", +        }); +    } + +    if first_char == 'd' && try_read("tri;") { +        return Some(CharRef { +            name: "tri;", +            characters: "\u{25bf}", +        }); +    } + +    if first_char == 'd' && try_read("zcy;") { +        return Some(CharRef { +            name: "zcy;", +            characters: "\u{45f}", +        }); +    } + +    if first_char == 'e' && try_read("Dot;") { +        return Some(CharRef { +            name: "Dot;", +            characters: "\u{2251}", +        }); +    } + +    if first_char == 'e' && try_read("cir;") { +        return Some(CharRef { +            name: "cir;", +            characters: "\u{2256}", +        }); +    } + +    if first_char == 'e' && try_read("circ") { +        return Some(CharRef { +            name: "circ", +            characters: "\u{ea}", +        }); +    } + +    if first_char == 'e' && try_read("dot;") { +        return Some(CharRef { +            name: "dot;", +            characters: "\u{117}", +        }); +    } + +    if first_char == 'e' && try_read("msp;") { +        return Some(CharRef { +            name: "msp;", +            characters: "\u{2003}", +        }); +    } + +    if first_char == 'e' && try_read("nsp;") { +        return Some(CharRef { +            name: "nsp;", +            characters: "\u{2002}", +        }); +    } + +    if first_char == 'e' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d556}", +        }); +    } + +    if first_char == 'e' && try_read("par;") { +        return Some(CharRef { +            name: "par;", +            characters: "\u{22d5}", +        }); +    } + +    if first_char == 'e' && try_read("psi;") { +        return Some(CharRef { +            name: "psi;", +            characters: "\u{3b5}", +        }); +    } + +    if first_char == 'e' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{212f}", +        }); +    } + +    if first_char == 'e' && try_read("sim;") { +        return Some(CharRef { +            name: "sim;", +            characters: "\u{2242}", +        }); +    } + +    if first_char == 'e' && try_read("uml;") { +        return Some(CharRef { +            name: "uml;", +            characters: "\u{eb}", +        }); +    } + +    if first_char == 'e' && try_read("uro;") { +        return Some(CharRef { +            name: "uro;", +            characters: "\u{20ac}", +        }); +    } + +    if first_char == 'e' && try_read("xcl;") { +        return Some(CharRef { +            name: "xcl;", +            characters: "\u{21}", +        }); +    } + +    if first_char == 'f' && try_read("lat;") { +        return Some(CharRef { +            name: "lat;", +            characters: "\u{266d}", +        }); +    } + +    if first_char == 'f' && try_read("nof;") { +        return Some(CharRef { +            name: "nof;", +            characters: "\u{192}", +        }); +    } + +    if first_char == 'f' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d557}", +        }); +    } + +    if first_char == 'f' && try_read("ork;") { +        return Some(CharRef { +            name: "ork;", +            characters: "\u{22d4}", +        }); +    } + +    if first_char == 'f' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4bb}", +        }); +    } + +    if first_char == 'g' && try_read("dot;") { +        return Some(CharRef { +            name: "dot;", +            characters: "\u{121}", +        }); +    } + +    if first_char == 'g' && try_read("eqq;") { +        return Some(CharRef { +            name: "eqq;", +            characters: "\u{2267}", +        }); +    } + +    if first_char == 'g' && try_read("esl;") { +        return Some(CharRef { +            name: "esl;", +            characters: "\u{22db}\u{fe00}", +        }); +    } + +    if first_char == 'g' && try_read("jcy;") { +        return Some(CharRef { +            name: "jcy;", +            characters: "\u{453}", +        }); +    } + +    if first_char == 'g' && try_read("nap;") { +        return Some(CharRef { +            name: "nap;", +            characters: "\u{2a8a}", +        }); +    } + +    if first_char == 'g' && try_read("neq;") { +        return Some(CharRef { +            name: "neq;", +            characters: "\u{2a88}", +        }); +    } + +    if first_char == 'g' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d558}", +        }); +    } + +    if first_char == 'g' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{210a}", +        }); +    } + +    if first_char == 'g' && try_read("sim;") { +        return Some(CharRef { +            name: "sim;", +            characters: "\u{2273}", +        }); +    } + +    if first_char == 'g' && try_read("tcc;") { +        return Some(CharRef { +            name: "tcc;", +            characters: "\u{2aa7}", +        }); +    } + +    if first_char == 'g' && try_read("vnE;") { +        return Some(CharRef { +            name: "vnE;", +            characters: "\u{2269}\u{fe00}", +        }); +    } + +    if first_char == 'h' && try_read("Arr;") { +        return Some(CharRef { +            name: "Arr;", +            characters: "\u{21d4}", +        }); +    } + +    if first_char == 'h' && try_read("alf;") { +        return Some(CharRef { +            name: "alf;", +            characters: "\u{bd}", +        }); +    } + +    if first_char == 'h' && try_read("arr;") { +        return Some(CharRef { +            name: "arr;", +            characters: "\u{2194}", +        }); +    } + +    if first_char == 'h' && try_read("bar;") { +        return Some(CharRef { +            name: "bar;", +            characters: "\u{210f}", +        }); +    } + +    if first_char == 'h' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d559}", +        }); +    } + +    if first_char == 'h' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4bd}", +        }); +    } + +    if first_char == 'i' && try_read("circ") { +        return Some(CharRef { +            name: "circ", +            characters: "\u{ee}", +        }); +    } + +    if first_char == 'i' && try_read("ecy;") { +        return Some(CharRef { +            name: "ecy;", +            characters: "\u{435}", +        }); +    } + +    if first_char == 'i' && try_read("excl") { +        return Some(CharRef { +            name: "excl", +            characters: "\u{a1}", +        }); +    } + +    if first_char == 'i' && try_read("mof;") { +        return Some(CharRef { +            name: "mof;", +            characters: "\u{22b7}", +        }); +    } + +    if first_char == 'i' && try_read("ocy;") { +        return Some(CharRef { +            name: "ocy;", +            characters: "\u{451}", +        }); +    } + +    if first_char == 'i' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d55a}", +        }); +    } + +    if first_char == 'i' && try_read("ota;") { +        return Some(CharRef { +            name: "ota;", +            characters: "\u{3b9}", +        }); +    } + +    if first_char == 'i' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4be}", +        }); +    } + +    if first_char == 'i' && try_read("sin;") { +        return Some(CharRef { +            name: "sin;", +            characters: "\u{2208}", +        }); +    } + +    if first_char == 'i' && try_read("uml;") { +        return Some(CharRef { +            name: "uml;", +            characters: "\u{ef}", +        }); +    } + +    if first_char == 'j' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d55b}", +        }); +    } + +    if first_char == 'j' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4bf}", +        }); +    } + +    if first_char == 'k' && try_read("hcy;") { +        return Some(CharRef { +            name: "hcy;", +            characters: "\u{445}", +        }); +    } + +    if first_char == 'k' && try_read("jcy;") { +        return Some(CharRef { +            name: "jcy;", +            characters: "\u{45c}", +        }); +    } + +    if first_char == 'k' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d55c}", +        }); +    } + +    if first_char == 'k' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4c0}", +        }); +    } + +    if first_char == 'l' && try_read("Arr;") { +        return Some(CharRef { +            name: "Arr;", +            characters: "\u{21d0}", +        }); +    } + +    if first_char == 'l' && try_read("Har;") { +        return Some(CharRef { +            name: "Har;", +            characters: "\u{2962}", +        }); +    } + +    if first_char == 'l' && try_read("ang;") { +        return Some(CharRef { +            name: "ang;", +            characters: "\u{27e8}", +        }); +    } + +    if first_char == 'l' && try_read("aquo") { +        return Some(CharRef { +            name: "aquo", +            characters: "\u{ab}", +        }); +    } + +    if first_char == 'l' && try_read("arr;") { +        return Some(CharRef { +            name: "arr;", +            characters: "\u{2190}", +        }); +    } + +    if first_char == 'l' && try_read("ate;") { +        return Some(CharRef { +            name: "ate;", +            characters: "\u{2aad}", +        }); +    } + +    if first_char == 'l' && try_read("cub;") { +        return Some(CharRef { +            name: "cub;", +            characters: "\u{7b}", +        }); +    } + +    if first_char == 'l' && try_read("dca;") { +        return Some(CharRef { +            name: "dca;", +            characters: "\u{2936}", +        }); +    } + +    if first_char == 'l' && try_read("dsh;") { +        return Some(CharRef { +            name: "dsh;", +            characters: "\u{21b2}", +        }); +    } + +    if first_char == 'l' && try_read("eqq;") { +        return Some(CharRef { +            name: "eqq;", +            characters: "\u{2266}", +        }); +    } + +    if first_char == 'l' && try_read("esg;") { +        return Some(CharRef { +            name: "esg;", +            characters: "\u{22da}\u{fe00}", +        }); +    } + +    if first_char == 'l' && try_read("jcy;") { +        return Some(CharRef { +            name: "jcy;", +            characters: "\u{459}", +        }); +    } + +    if first_char == 'l' && try_read("nap;") { +        return Some(CharRef { +            name: "nap;", +            characters: "\u{2a89}", +        }); +    } + +    if first_char == 'l' && try_read("neq;") { +        return Some(CharRef { +            name: "neq;", +            characters: "\u{2a87}", +        }); +    } + +    if first_char == 'l' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d55d}", +        }); +    } + +    if first_char == 'l' && try_read("ozf;") { +        return Some(CharRef { +            name: "ozf;", +            characters: "\u{29eb}", +        }); +    } + +    if first_char == 'l' && try_read("par;") { +        return Some(CharRef { +            name: "par;", +            characters: "\u{28}", +        }); +    } + +    if first_char == 'l' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4c1}", +        }); +    } + +    if first_char == 'l' && try_read("sim;") { +        return Some(CharRef { +            name: "sim;", +            characters: "\u{2272}", +        }); +    } + +    if first_char == 'l' && try_read("sqb;") { +        return Some(CharRef { +            name: "sqb;", +            characters: "\u{5b}", +        }); +    } + +    if first_char == 'l' && try_read("tcc;") { +        return Some(CharRef { +            name: "tcc;", +            characters: "\u{2aa6}", +        }); +    } + +    if first_char == 'l' && try_read("tri;") { +        return Some(CharRef { +            name: "tri;", +            characters: "\u{25c3}", +        }); +    } + +    if first_char == 'l' && try_read("vnE;") { +        return Some(CharRef { +            name: "vnE;", +            characters: "\u{2268}\u{fe00}", +        }); +    } + +    if first_char == 'm' && try_read("acr;") { +        return Some(CharRef { +            name: "acr;", +            characters: "\u{af}", +        }); +    } + +    if first_char == 'm' && try_read("ale;") { +        return Some(CharRef { +            name: "ale;", +            characters: "\u{2642}", +        }); +    } + +    if first_char == 'm' && try_read("alt;") { +        return Some(CharRef { +            name: "alt;", +            characters: "\u{2720}", +        }); +    } + +    if first_char == 'm' && try_read("icro") { +        return Some(CharRef { +            name: "icro", +            characters: "\u{b5}", +        }); +    } + +    if first_char == 'm' && try_read("lcp;") { +        return Some(CharRef { +            name: "lcp;", +            characters: "\u{2adb}", +        }); +    } + +    if first_char == 'm' && try_read("ldr;") { +        return Some(CharRef { +            name: "ldr;", +            characters: "\u{2026}", +        }); +    } + +    if first_char == 'm' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d55e}", +        }); +    } + +    if first_char == 'm' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4c2}", +        }); +    } + +    if first_char == 'n' && try_read("Gtv;") { +        return Some(CharRef { +            name: "Gtv;", +            characters: "\u{226b}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("Ltv;") { +        return Some(CharRef { +            name: "Ltv;", +            characters: "\u{226a}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("ang;") { +        return Some(CharRef { +            name: "ang;", +            characters: "\u{2220}\u{20d2}", +        }); +    } + +    if first_char == 'n' && try_read("apE;") { +        return Some(CharRef { +            name: "apE;", +            characters: "\u{2a70}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("bsp;") { +        return Some(CharRef { +            name: "bsp;", +            characters: "\u{a0}", +        }); +    } + +    if first_char == 'n' && try_read("cap;") { +        return Some(CharRef { +            name: "cap;", +            characters: "\u{2a43}", +        }); +    } + +    if first_char == 'n' && try_read("cup;") { +        return Some(CharRef { +            name: "cup;", +            characters: "\u{2a42}", +        }); +    } + +    if first_char == 'n' && try_read("geq;") { +        return Some(CharRef { +            name: "geq;", +            characters: "\u{2271}", +        }); +    } + +    if first_char == 'n' && try_read("ges;") { +        return Some(CharRef { +            name: "ges;", +            characters: "\u{2a7e}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("gtr;") { +        return Some(CharRef { +            name: "gtr;", +            characters: "\u{226f}", +        }); +    } + +    if first_char == 'n' && try_read("isd;") { +        return Some(CharRef { +            name: "isd;", +            characters: "\u{22fa}", +        }); +    } + +    if first_char == 'n' && try_read("jcy;") { +        return Some(CharRef { +            name: "jcy;", +            characters: "\u{45a}", +        }); +    } + +    if first_char == 'n' && try_read("ldr;") { +        return Some(CharRef { +            name: "ldr;", +            characters: "\u{2025}", +        }); +    } + +    if first_char == 'n' && try_read("leq;") { +        return Some(CharRef { +            name: "leq;", +            characters: "\u{2270}", +        }); +    } + +    if first_char == 'n' && try_read("les;") { +        return Some(CharRef { +            name: "les;", +            characters: "\u{2a7d}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("mid;") { +        return Some(CharRef { +            name: "mid;", +            characters: "\u{2224}", +        }); +    } + +    if first_char == 'n' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d55f}", +        }); +    } + +    if first_char == 'n' && try_read("par;") { +        return Some(CharRef { +            name: "par;", +            characters: "\u{2226}", +        }); +    } + +    if first_char == 'n' && try_read("pre;") { +        return Some(CharRef { +            name: "pre;", +            characters: "\u{2aaf}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("sce;") { +        return Some(CharRef { +            name: "sce;", +            characters: "\u{2ab0}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4c3}", +        }); +    } + +    if first_char == 'n' && try_read("sim;") { +        return Some(CharRef { +            name: "sim;", +            characters: "\u{2241}", +        }); +    } + +    if first_char == 'n' && try_read("sub;") { +        return Some(CharRef { +            name: "sub;", +            characters: "\u{2284}", +        }); +    } + +    if first_char == 'n' && try_read("sup;") { +        return Some(CharRef { +            name: "sup;", +            characters: "\u{2285}", +        }); +    } + +    if first_char == 'n' && try_read("tgl;") { +        return Some(CharRef { +            name: "tgl;", +            characters: "\u{2279}", +        }); +    } + +    if first_char == 'n' && try_read("tlg;") { +        return Some(CharRef { +            name: "tlg;", +            characters: "\u{2278}", +        }); +    } + +    if first_char == 'n' && try_read("vap;") { +        return Some(CharRef { +            name: "vap;", +            characters: "\u{224d}\u{20d2}", +        }); +    } + +    if first_char == 'n' && try_read("vge;") { +        return Some(CharRef { +            name: "vge;", +            characters: "\u{2265}\u{20d2}", +        }); +    } + +    if first_char == 'n' && try_read("vgt;") { +        return Some(CharRef { +            name: "vgt;", +            characters: "\u{3e}\u{20d2}", +        }); +    } + +    if first_char == 'n' && try_read("vle;") { +        return Some(CharRef { +            name: "vle;", +            characters: "\u{2264}\u{20d2}", +        }); +    } + +    if first_char == 'n' && try_read("vlt;") { +        return Some(CharRef { +            name: "vlt;", +            characters: "\u{3c}\u{20d2}", +        }); +    } + +    if first_char == 'o' && try_read("ast;") { +        return Some(CharRef { +            name: "ast;", +            characters: "\u{229b}", +        }); +    } + +    if first_char == 'o' && try_read("cir;") { +        return Some(CharRef { +            name: "cir;", +            characters: "\u{229a}", +        }); +    } + +    if first_char == 'o' && try_read("circ") { +        return Some(CharRef { +            name: "circ", +            characters: "\u{f4}", +        }); +    } + +    if first_char == 'o' && try_read("div;") { +        return Some(CharRef { +            name: "div;", +            characters: "\u{2a38}", +        }); +    } + +    if first_char == 'o' && try_read("dot;") { +        return Some(CharRef { +            name: "dot;", +            characters: "\u{2299}", +        }); +    } + +    if first_char == 'o' && try_read("gon;") { +        return Some(CharRef { +            name: "gon;", +            characters: "\u{2db}", +        }); +    } + +    if first_char == 'o' && try_read("int;") { +        return Some(CharRef { +            name: "int;", +            characters: "\u{222e}", +        }); +    } + +    if first_char == 'o' && try_read("mid;") { +        return Some(CharRef { +            name: "mid;", +            characters: "\u{29b6}", +        }); +    } + +    if first_char == 'o' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d560}", +        }); +    } + +    if first_char == 'o' && try_read("par;") { +        return Some(CharRef { +            name: "par;", +            characters: "\u{29b7}", +        }); +    } + +    if first_char == 'o' && try_read("rdf;") { +        return Some(CharRef { +            name: "rdf;", +            characters: "\u{aa}", +        }); +    } + +    if first_char == 'o' && try_read("rdm;") { +        return Some(CharRef { +            name: "rdm;", +            characters: "\u{ba}", +        }); +    } + +    if first_char == 'o' && try_read("ror;") { +        return Some(CharRef { +            name: "ror;", +            characters: "\u{2a56}", +        }); +    } + +    if first_char == 'o' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{2134}", +        }); +    } + +    if first_char == 'o' && try_read("sol;") { +        return Some(CharRef { +            name: "sol;", +            characters: "\u{2298}", +        }); +    } + +    if first_char == 'o' && try_read("uml;") { +        return Some(CharRef { +            name: "uml;", +            characters: "\u{f6}", +        }); +    } + +    if first_char == 'p' && try_read("ara;") { +        return Some(CharRef { +            name: "ara;", +            characters: "\u{b6}", +        }); +    } + +    if first_char == 'p' && try_read("art;") { +        return Some(CharRef { +            name: "art;", +            characters: "\u{2202}", +        }); +    } + +    if first_char == 'p' && try_read("erp;") { +        return Some(CharRef { +            name: "erp;", +            characters: "\u{22a5}", +        }); +    } + +    if first_char == 'p' && try_read("hiv;") { +        return Some(CharRef { +            name: "hiv;", +            characters: "\u{3d5}", +        }); +    } + +    if first_char == 'p' && try_read("lus;") { +        return Some(CharRef { +            name: "lus;", +            characters: "\u{2b}", +        }); +    } + +    if first_char == 'p' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d561}", +        }); +    } + +    if first_char == 'p' && try_read("ound") { +        return Some(CharRef { +            name: "ound", +            characters: "\u{a3}", +        }); +    } + +    if first_char == 'p' && try_read("rap;") { +        return Some(CharRef { +            name: "rap;", +            characters: "\u{2ab7}", +        }); +    } + +    if first_char == 'p' && try_read("rec;") { +        return Some(CharRef { +            name: "rec;", +            characters: "\u{227a}", +        }); +    } + +    if first_char == 'p' && try_read("rnE;") { +        return Some(CharRef { +            name: "rnE;", +            characters: "\u{2ab5}", +        }); +    } + +    if first_char == 'p' && try_read("rod;") { +        return Some(CharRef { +            name: "rod;", +            characters: "\u{220f}", +        }); +    } + +    if first_char == 'p' && try_read("rop;") { +        return Some(CharRef { +            name: "rop;", +            characters: "\u{221d}", +        }); +    } + +    if first_char == 'p' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4c5}", +        }); +    } + +    if first_char == 'q' && try_read("int;") { +        return Some(CharRef { +            name: "int;", +            characters: "\u{2a0c}", +        }); +    } + +    if first_char == 'q' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d562}", +        }); +    } + +    if first_char == 'q' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4c6}", +        }); +    } + +    if first_char == 'q' && try_read("uot;") { +        return Some(CharRef { +            name: "uot;", +            characters: "\u{22}", +        }); +    } + +    if first_char == 'r' && try_read("Arr;") { +        return Some(CharRef { +            name: "Arr;", +            characters: "\u{21d2}", +        }); +    } + +    if first_char == 'r' && try_read("Har;") { +        return Some(CharRef { +            name: "Har;", +            characters: "\u{2964}", +        }); +    } + +    if first_char == 'r' && try_read("ace;") { +        return Some(CharRef { +            name: "ace;", +            characters: "\u{223d}\u{331}", +        }); +    } + +    if first_char == 'r' && try_read("ang;") { +        return Some(CharRef { +            name: "ang;", +            characters: "\u{27e9}", +        }); +    } + +    if first_char == 'r' && try_read("aquo") { +        return Some(CharRef { +            name: "aquo", +            characters: "\u{bb}", +        }); +    } + +    if first_char == 'r' && try_read("arr;") { +        return Some(CharRef { +            name: "arr;", +            characters: "\u{2192}", +        }); +    } + +    if first_char == 'r' && try_read("cub;") { +        return Some(CharRef { +            name: "cub;", +            characters: "\u{7d}", +        }); +    } + +    if first_char == 'r' && try_read("dca;") { +        return Some(CharRef { +            name: "dca;", +            characters: "\u{2937}", +        }); +    } + +    if first_char == 'r' && try_read("dsh;") { +        return Some(CharRef { +            name: "dsh;", +            characters: "\u{21b3}", +        }); +    } + +    if first_char == 'r' && try_read("eal;") { +        return Some(CharRef { +            name: "eal;", +            characters: "\u{211c}", +        }); +    } + +    if first_char == 'r' && try_read("ect;") { +        return Some(CharRef { +            name: "ect;", +            characters: "\u{25ad}", +        }); +    } + +    if first_char == 'r' && try_read("hov;") { +        return Some(CharRef { +            name: "hov;", +            characters: "\u{3f1}", +        }); +    } + +    if first_char == 'r' && try_read("ing;") { +        return Some(CharRef { +            name: "ing;", +            characters: "\u{2da}", +        }); +    } + +    if first_char == 'r' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d563}", +        }); +    } + +    if first_char == 'r' && try_read("par;") { +        return Some(CharRef { +            name: "par;", +            characters: "\u{29}", +        }); +    } + +    if first_char == 'r' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4c7}", +        }); +    } + +    if first_char == 'r' && try_read("sqb;") { +        return Some(CharRef { +            name: "sqb;", +            characters: "\u{5d}", +        }); +    } + +    if first_char == 'r' && try_read("tri;") { +        return Some(CharRef { +            name: "tri;", +            characters: "\u{25b9}", +        }); +    } + +    if first_char == 's' && try_read("cap;") { +        return Some(CharRef { +            name: "cap;", +            characters: "\u{2ab8}", +        }); +    } + +    if first_char == 's' && try_read("cnE;") { +        return Some(CharRef { +            name: "cnE;", +            characters: "\u{2ab6}", +        }); +    } + +    if first_char == 's' && try_read("dot;") { +        return Some(CharRef { +            name: "dot;", +            characters: "\u{22c5}", +        }); +    } + +    if first_char == 's' && try_read("ect;") { +        return Some(CharRef { +            name: "ect;", +            characters: "\u{a7}", +        }); +    } + +    if first_char == 's' && try_read("emi;") { +        return Some(CharRef { +            name: "emi;", +            characters: "\u{3b}", +        }); +    } + +    if first_char == 's' && try_read("ext;") { +        return Some(CharRef { +            name: "ext;", +            characters: "\u{2736}", +        }); +    } + +    if first_char == 's' && try_read("hcy;") { +        return Some(CharRef { +            name: "hcy;", +            characters: "\u{448}", +        }); +    } + +    if first_char == 's' && try_read("ime;") { +        return Some(CharRef { +            name: "ime;", +            characters: "\u{2243}", +        }); +    } + +    if first_char == 's' && try_read("img;") { +        return Some(CharRef { +            name: "img;", +            characters: "\u{2a9e}", +        }); +    } + +    if first_char == 's' && try_read("iml;") { +        return Some(CharRef { +            name: "iml;", +            characters: "\u{2a9d}", +        }); +    } + +    if first_char == 's' && try_read("mid;") { +        return Some(CharRef { +            name: "mid;", +            characters: "\u{2223}", +        }); +    } + +    if first_char == 's' && try_read("mte;") { +        return Some(CharRef { +            name: "mte;", +            characters: "\u{2aac}", +        }); +    } + +    if first_char == 's' && try_read("olb;") { +        return Some(CharRef { +            name: "olb;", +            characters: "\u{29c4}", +        }); +    } + +    if first_char == 's' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d564}", +        }); +    } + +    if first_char == 's' && try_read("par;") { +        return Some(CharRef { +            name: "par;", +            characters: "\u{2225}", +        }); +    } + +    if first_char == 's' && try_read("quf;") { +        return Some(CharRef { +            name: "quf;", +            characters: "\u{25aa}", +        }); +    } + +    if first_char == 's' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4c8}", +        }); +    } + +    if first_char == 's' && try_read("tar;") { +        return Some(CharRef { +            name: "tar;", +            characters: "\u{2606}", +        }); +    } + +    if first_char == 's' && try_read("ubE;") { +        return Some(CharRef { +            name: "ubE;", +            characters: "\u{2ac5}", +        }); +    } + +    if first_char == 's' && try_read("ube;") { +        return Some(CharRef { +            name: "ube;", +            characters: "\u{2286}", +        }); +    } + +    if first_char == 's' && try_read("ucc;") { +        return Some(CharRef { +            name: "ucc;", +            characters: "\u{227b}", +        }); +    } + +    if first_char == 's' && try_read("ung;") { +        return Some(CharRef { +            name: "ung;", +            characters: "\u{266a}", +        }); +    } + +    if first_char == 's' && try_read("up1;") { +        return Some(CharRef { +            name: "up1;", +            characters: "\u{b9}", +        }); +    } + +    if first_char == 's' && try_read("up2;") { +        return Some(CharRef { +            name: "up2;", +            characters: "\u{b2}", +        }); +    } + +    if first_char == 's' && try_read("up3;") { +        return Some(CharRef { +            name: "up3;", +            characters: "\u{b3}", +        }); +    } + +    if first_char == 's' && try_read("upE;") { +        return Some(CharRef { +            name: "upE;", +            characters: "\u{2ac6}", +        }); +    } + +    if first_char == 's' && try_read("upe;") { +        return Some(CharRef { +            name: "upe;", +            characters: "\u{2287}", +        }); +    } + +    if first_char == 's' && try_read("zlig") { +        return Some(CharRef { +            name: "zlig", +            characters: "\u{df}", +        }); +    } + +    if first_char == 't' && try_read("brk;") { +        return Some(CharRef { +            name: "brk;", +            characters: "\u{23b4}", +        }); +    } + +    if first_char == 't' && try_read("dot;") { +        return Some(CharRef { +            name: "dot;", +            characters: "\u{20db}", +        }); +    } + +    if first_char == 't' && try_read("horn") { +        return Some(CharRef { +            name: "horn", +            characters: "\u{fe}", +        }); +    } + +    if first_char == 't' && try_read("imes") { +        return Some(CharRef { +            name: "imes", +            characters: "\u{d7}", +        }); +    } + +    if first_char == 't' && try_read("int;") { +        return Some(CharRef { +            name: "int;", +            characters: "\u{222d}", +        }); +    } + +    if first_char == 't' && try_read("oea;") { +        return Some(CharRef { +            name: "oea;", +            characters: "\u{2928}", +        }); +    } + +    if first_char == 't' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d565}", +        }); +    } + +    if first_char == 't' && try_read("osa;") { +        return Some(CharRef { +            name: "osa;", +            characters: "\u{2929}", +        }); +    } + +    if first_char == 't' && try_read("rie;") { +        return Some(CharRef { +            name: "rie;", +            characters: "\u{225c}", +        }); +    } + +    if first_char == 't' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4c9}", +        }); +    } + +    if first_char == 't' && try_read("scy;") { +        return Some(CharRef { +            name: "scy;", +            characters: "\u{446}", +        }); +    } + +    if first_char == 'u' && try_read("Arr;") { +        return Some(CharRef { +            name: "Arr;", +            characters: "\u{21d1}", +        }); +    } + +    if first_char == 'u' && try_read("Har;") { +        return Some(CharRef { +            name: "Har;", +            characters: "\u{2963}", +        }); +    } + +    if first_char == 'u' && try_read("arr;") { +        return Some(CharRef { +            name: "arr;", +            characters: "\u{2191}", +        }); +    } + +    if first_char == 'u' && try_read("circ") { +        return Some(CharRef { +            name: "circ", +            characters: "\u{fb}", +        }); +    } + +    if first_char == 'u' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d566}", +        }); +    } + +    if first_char == 'u' && try_read("psi;") { +        return Some(CharRef { +            name: "psi;", +            characters: "\u{3c5}", +        }); +    } + +    if first_char == 'u' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4ca}", +        }); +    } + +    if first_char == 'u' && try_read("tri;") { +        return Some(CharRef { +            name: "tri;", +            characters: "\u{25b5}", +        }); +    } + +    if first_char == 'u' && try_read("uml;") { +        return Some(CharRef { +            name: "uml;", +            characters: "\u{fc}", +        }); +    } + +    if first_char == 'v' && try_read("Arr;") { +        return Some(CharRef { +            name: "Arr;", +            characters: "\u{21d5}", +        }); +    } + +    if first_char == 'v' && try_read("Bar;") { +        return Some(CharRef { +            name: "Bar;", +            characters: "\u{2ae8}", +        }); +    } + +    if first_char == 'v' && try_read("arr;") { +        return Some(CharRef { +            name: "arr;", +            characters: "\u{2195}", +        }); +    } + +    if first_char == 'v' && try_read("ert;") { +        return Some(CharRef { +            name: "ert;", +            characters: "\u{7c}", +        }); +    } + +    if first_char == 'v' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d567}", +        }); +    } + +    if first_char == 'v' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4cb}", +        }); +    } + +    if first_char == 'w' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d568}", +        }); +    } + +    if first_char == 'w' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4cc}", +        }); +    } + +    if first_char == 'x' && try_read("cap;") { +        return Some(CharRef { +            name: "cap;", +            characters: "\u{22c2}", +        }); +    } + +    if first_char == 'x' && try_read("cup;") { +        return Some(CharRef { +            name: "cup;", +            characters: "\u{22c3}", +        }); +    } + +    if first_char == 'x' && try_read("map;") { +        return Some(CharRef { +            name: "map;", +            characters: "\u{27fc}", +        }); +    } + +    if first_char == 'x' && try_read("nis;") { +        return Some(CharRef { +            name: "nis;", +            characters: "\u{22fb}", +        }); +    } + +    if first_char == 'x' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d569}", +        }); +    } + +    if first_char == 'x' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4cd}", +        }); +    } + +    if first_char == 'x' && try_read("vee;") { +        return Some(CharRef { +            name: "vee;", +            characters: "\u{22c1}", +        }); +    } + +    if first_char == 'y' && try_read("acy;") { +        return Some(CharRef { +            name: "acy;", +            characters: "\u{44f}", +        }); +    } + +    if first_char == 'y' && try_read("icy;") { +        return Some(CharRef { +            name: "icy;", +            characters: "\u{457}", +        }); +    } + +    if first_char == 'y' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d56a}", +        }); +    } + +    if first_char == 'y' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4ce}", +        }); +    } + +    if first_char == 'y' && try_read("ucy;") { +        return Some(CharRef { +            name: "ucy;", +            characters: "\u{44e}", +        }); +    } + +    if first_char == 'y' && try_read("uml;") { +        return Some(CharRef { +            name: "uml;", +            characters: "\u{ff}", +        }); +    } + +    if first_char == 'z' && try_read("dot;") { +        return Some(CharRef { +            name: "dot;", +            characters: "\u{17c}", +        }); +    } + +    if first_char == 'z' && try_read("eta;") { +        return Some(CharRef { +            name: "eta;", +            characters: "\u{3b6}", +        }); +    } + +    if first_char == 'z' && try_read("hcy;") { +        return Some(CharRef { +            name: "hcy;", +            characters: "\u{436}", +        }); +    } + +    if first_char == 'z' && try_read("opf;") { +        return Some(CharRef { +            name: "opf;", +            characters: "\u{1d56b}", +        }); +    } + +    if first_char == 'z' && try_read("scr;") { +        return Some(CharRef { +            name: "scr;", +            characters: "\u{1d4cf}", +        }); +    } + +    if first_char == 'z' && try_read("wnj;") { +        return Some(CharRef { +            name: "wnj;", +            characters: "\u{200c}", +        }); +    } + +    if first_char == 'A' && try_read("MP;") { +        return Some(CharRef { +            name: "MP;", +            characters: "\u{26}", +        }); +    } + +    if first_char == 'A' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{410}", +        }); +    } + +    if first_char == 'A' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d504}", +        }); +    } + +    if first_char == 'A' && try_read("nd;") { +        return Some(CharRef { +            name: "nd;", +            characters: "\u{2a53}", +        }); +    } + +    if first_char == 'A' && try_read("uml") { +        return Some(CharRef { +            name: "uml", +            characters: "\u{c4}", +        }); +    } + +    if first_char == 'B' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{411}", +        }); +    } + +    if first_char == 'B' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d505}", +        }); +    } + +    if first_char == 'C' && try_read("OPY") { +        return Some(CharRef { +            name: "OPY", +            characters: "\u{a9}", +        }); +    } + +    if first_char == 'C' && try_read("ap;") { +        return Some(CharRef { +            name: "ap;", +            characters: "\u{22d2}", +        }); +    } + +    if first_char == 'C' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{212d}", +        }); +    } + +    if first_char == 'C' && try_read("hi;") { +        return Some(CharRef { +            name: "hi;", +            characters: "\u{3a7}", +        }); +    } + +    if first_char == 'C' && try_read("up;") { +        return Some(CharRef { +            name: "up;", +            characters: "\u{22d3}", +        }); +    } + +    if first_char == 'D' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{414}", +        }); +    } + +    if first_char == 'D' && try_read("el;") { +        return Some(CharRef { +            name: "el;", +            characters: "\u{2207}", +        }); +    } + +    if first_char == 'D' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d507}", +        }); +    } + +    if first_char == 'D' && try_read("ot;") { +        return Some(CharRef { +            name: "ot;", +            characters: "\u{a8}", +        }); +    } + +    if first_char == 'E' && try_read("NG;") { +        return Some(CharRef { +            name: "NG;", +            characters: "\u{14a}", +        }); +    } + +    if first_char == 'E' && try_read("TH;") { +        return Some(CharRef { +            name: "TH;", +            characters: "\u{d0}", +        }); +    } + +    if first_char == 'E' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{42d}", +        }); +    } + +    if first_char == 'E' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d508}", +        }); +    } + +    if first_char == 'E' && try_read("ta;") { +        return Some(CharRef { +            name: "ta;", +            characters: "\u{397}", +        }); +    } + +    if first_char == 'E' && try_read("uml") { +        return Some(CharRef { +            name: "uml", +            characters: "\u{cb}", +        }); +    } + +    if first_char == 'F' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{424}", +        }); +    } + +    if first_char == 'F' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d509}", +        }); +    } + +    if first_char == 'G' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{413}", +        }); +    } + +    if first_char == 'G' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d50a}", +        }); +    } + +    if first_char == 'H' && try_read("at;") { +        return Some(CharRef { +            name: "at;", +            characters: "\u{5e}", +        }); +    } + +    if first_char == 'H' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{210c}", +        }); +    } + +    if first_char == 'I' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{418}", +        }); +    } + +    if first_char == 'I' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{2111}", +        }); +    } + +    if first_char == 'I' && try_read("nt;") { +        return Some(CharRef { +            name: "nt;", +            characters: "\u{222c}", +        }); +    } + +    if first_char == 'I' && try_read("uml") { +        return Some(CharRef { +            name: "uml", +            characters: "\u{cf}", +        }); +    } + +    if first_char == 'J' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{419}", +        }); +    } + +    if first_char == 'J' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d50d}", +        }); +    } + +    if first_char == 'K' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{41a}", +        }); +    } + +    if first_char == 'K' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d50e}", +        }); +    } + +    if first_char == 'L' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{41b}", +        }); +    } + +    if first_char == 'L' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d50f}", +        }); +    } + +    if first_char == 'L' && try_read("sh;") { +        return Some(CharRef { +            name: "sh;", +            characters: "\u{21b0}", +        }); +    } + +    if first_char == 'M' && try_read("ap;") { +        return Some(CharRef { +            name: "ap;", +            characters: "\u{2905}", +        }); +    } + +    if first_char == 'M' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{41c}", +        }); +    } + +    if first_char == 'M' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d510}", +        }); +    } + +    if first_char == 'N' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{41d}", +        }); +    } + +    if first_char == 'N' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d511}", +        }); +    } + +    if first_char == 'N' && try_read("ot;") { +        return Some(CharRef { +            name: "ot;", +            characters: "\u{2aec}", +        }); +    } + +    if first_char == 'O' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{41e}", +        }); +    } + +    if first_char == 'O' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d512}", +        }); +    } + +    if first_char == 'O' && try_read("uml") { +        return Some(CharRef { +            name: "uml", +            characters: "\u{d6}", +        }); +    } + +    if first_char == 'P' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{41f}", +        }); +    } + +    if first_char == 'P' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d513}", +        }); +    } + +    if first_char == 'P' && try_read("hi;") { +        return Some(CharRef { +            name: "hi;", +            characters: "\u{3a6}", +        }); +    } + +    if first_char == 'P' && try_read("si;") { +        return Some(CharRef { +            name: "si;", +            characters: "\u{3a8}", +        }); +    } + +    if first_char == 'Q' && try_read("UOT") { +        return Some(CharRef { +            name: "UOT", +            characters: "\u{22}", +        }); +    } + +    if first_char == 'Q' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d514}", +        }); +    } + +    if first_char == 'R' && try_read("EG;") { +        return Some(CharRef { +            name: "EG;", +            characters: "\u{ae}", +        }); +    } + +    if first_char == 'R' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{420}", +        }); +    } + +    if first_char == 'R' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{211c}", +        }); +    } + +    if first_char == 'R' && try_read("ho;") { +        return Some(CharRef { +            name: "ho;", +            characters: "\u{3a1}", +        }); +    } + +    if first_char == 'R' && try_read("sh;") { +        return Some(CharRef { +            name: "sh;", +            characters: "\u{21b1}", +        }); +    } + +    if first_char == 'S' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{421}", +        }); +    } + +    if first_char == 'S' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d516}", +        }); +    } + +    if first_char == 'S' && try_read("ub;") { +        return Some(CharRef { +            name: "ub;", +            characters: "\u{22d0}", +        }); +    } + +    if first_char == 'S' && try_read("um;") { +        return Some(CharRef { +            name: "um;", +            characters: "\u{2211}", +        }); +    } + +    if first_char == 'S' && try_read("up;") { +        return Some(CharRef { +            name: "up;", +            characters: "\u{22d1}", +        }); +    } + +    if first_char == 'T' && try_read("ab;") { +        return Some(CharRef { +            name: "ab;", +            characters: "\u{9}", +        }); +    } + +    if first_char == 'T' && try_read("au;") { +        return Some(CharRef { +            name: "au;", +            characters: "\u{3a4}", +        }); +    } + +    if first_char == 'T' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{422}", +        }); +    } + +    if first_char == 'T' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d517}", +        }); +    } + +    if first_char == 'U' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{423}", +        }); +    } + +    if first_char == 'U' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d518}", +        }); +    } + +    if first_char == 'U' && try_read("uml") { +        return Some(CharRef { +            name: "uml", +            characters: "\u{dc}", +        }); +    } + +    if first_char == 'V' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{412}", +        }); +    } + +    if first_char == 'V' && try_read("ee;") { +        return Some(CharRef { +            name: "ee;", +            characters: "\u{22c1}", +        }); +    } + +    if first_char == 'V' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d519}", +        }); +    } + +    if first_char == 'W' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d51a}", +        }); +    } + +    if first_char == 'X' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d51b}", +        }); +    } + +    if first_char == 'Y' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{42b}", +        }); +    } + +    if first_char == 'Y' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d51c}", +        }); +    } + +    if first_char == 'Z' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{417}", +        }); +    } + +    if first_char == 'Z' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{2128}", +        }); +    } + +    if first_char == 'a' && try_read("cE;") { +        return Some(CharRef { +            name: "cE;", +            characters: "\u{223e}\u{333}", +        }); +    } + +    if first_char == 'a' && try_read("cd;") { +        return Some(CharRef { +            name: "cd;", +            characters: "\u{223f}", +        }); +    } + +    if first_char == 'a' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{430}", +        }); +    } + +    if first_char == 'a' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d51e}", +        }); +    } + +    if first_char == 'a' && try_read("mp;") { +        return Some(CharRef { +            name: "mp;", +            characters: "\u{26}", +        }); +    } + +    if first_char == 'a' && try_read("nd;") { +        return Some(CharRef { +            name: "nd;", +            characters: "\u{2227}", +        }); +    } + +    if first_char == 'a' && try_read("ng;") { +        return Some(CharRef { +            name: "ng;", +            characters: "\u{2220}", +        }); +    } + +    if first_char == 'a' && try_read("pE;") { +        return Some(CharRef { +            name: "pE;", +            characters: "\u{2a70}", +        }); +    } + +    if first_char == 'a' && try_read("pe;") { +        return Some(CharRef { +            name: "pe;", +            characters: "\u{224a}", +        }); +    } + +    if first_char == 'a' && try_read("st;") { +        return Some(CharRef { +            name: "st;", +            characters: "\u{2a}", +        }); +    } + +    if first_char == 'a' && try_read("uml") { +        return Some(CharRef { +            name: "uml", +            characters: "\u{e4}", +        }); +    } + +    if first_char == 'b' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{431}", +        }); +    } + +    if first_char == 'b' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d51f}", +        }); +    } + +    if first_char == 'b' && try_read("ne;") { +        return Some(CharRef { +            name: "ne;", +            characters: "\u{3d}\u{20e5}", +        }); +    } + +    if first_char == 'b' && try_read("ot;") { +        return Some(CharRef { +            name: "ot;", +            characters: "\u{22a5}", +        }); +    } + +    if first_char == 'c' && try_read("ap;") { +        return Some(CharRef { +            name: "ap;", +            characters: "\u{2229}", +        }); +    } + +    if first_char == 'c' && try_read("ent") { +        return Some(CharRef { +            name: "ent", +            characters: "\u{a2}", +        }); +    } + +    if first_char == 'c' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d520}", +        }); +    } + +    if first_char == 'c' && try_read("hi;") { +        return Some(CharRef { +            name: "hi;", +            characters: "\u{3c7}", +        }); +    } + +    if first_char == 'c' && try_read("ir;") { +        return Some(CharRef { +            name: "ir;", +            characters: "\u{25cb}", +        }); +    } + +    if first_char == 'c' && try_read("opy") { +        return Some(CharRef { +            name: "opy", +            characters: "\u{a9}", +        }); +    } + +    if first_char == 'c' && try_read("up;") { +        return Some(CharRef { +            name: "up;", +            characters: "\u{222a}", +        }); +    } + +    if first_char == 'd' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{434}", +        }); +    } + +    if first_char == 'd' && try_read("eg;") { +        return Some(CharRef { +            name: "eg;", +            characters: "\u{b0}", +        }); +    } + +    if first_char == 'd' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d521}", +        }); +    } + +    if first_char == 'd' && try_read("ie;") { +        return Some(CharRef { +            name: "ie;", +            characters: "\u{a8}", +        }); +    } + +    if first_char == 'd' && try_read("iv;") { +        return Some(CharRef { +            name: "iv;", +            characters: "\u{f7}", +        }); +    } + +    if first_char == 'd' && try_read("ot;") { +        return Some(CharRef { +            name: "ot;", +            characters: "\u{2d9}", +        }); +    } + +    if first_char == 'e' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{44d}", +        }); +    } + +    if first_char == 'e' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d522}", +        }); +    } + +    if first_char == 'e' && try_read("gs;") { +        return Some(CharRef { +            name: "gs;", +            characters: "\u{2a96}", +        }); +    } + +    if first_char == 'e' && try_read("ll;") { +        return Some(CharRef { +            name: "ll;", +            characters: "\u{2113}", +        }); +    } + +    if first_char == 'e' && try_read("ls;") { +        return Some(CharRef { +            name: "ls;", +            characters: "\u{2a95}", +        }); +    } + +    if first_char == 'e' && try_read("ng;") { +        return Some(CharRef { +            name: "ng;", +            characters: "\u{14b}", +        }); +    } + +    if first_char == 'e' && try_read("ta;") { +        return Some(CharRef { +            name: "ta;", +            characters: "\u{3b7}", +        }); +    } + +    if first_char == 'e' && try_read("th;") { +        return Some(CharRef { +            name: "th;", +            characters: "\u{f0}", +        }); +    } + +    if first_char == 'e' && try_read("uml") { +        return Some(CharRef { +            name: "uml", +            characters: "\u{eb}", +        }); +    } + +    if first_char == 'f' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{444}", +        }); +    } + +    if first_char == 'f' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d523}", +        }); +    } + +    if first_char == 'g' && try_read("El;") { +        return Some(CharRef { +            name: "El;", +            characters: "\u{2a8c}", +        }); +    } + +    if first_char == 'g' && try_read("ap;") { +        return Some(CharRef { +            name: "ap;", +            characters: "\u{2a86}", +        }); +    } + +    if first_char == 'g' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{433}", +        }); +    } + +    if first_char == 'g' && try_read("el;") { +        return Some(CharRef { +            name: "el;", +            characters: "\u{22db}", +        }); +    } + +    if first_char == 'g' && try_read("eq;") { +        return Some(CharRef { +            name: "eq;", +            characters: "\u{2265}", +        }); +    } + +    if first_char == 'g' && try_read("es;") { +        return Some(CharRef { +            name: "es;", +            characters: "\u{2a7e}", +        }); +    } + +    if first_char == 'g' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d524}", +        }); +    } + +    if first_char == 'g' && try_read("gg;") { +        return Some(CharRef { +            name: "gg;", +            characters: "\u{22d9}", +        }); +    } + +    if first_char == 'g' && try_read("lE;") { +        return Some(CharRef { +            name: "lE;", +            characters: "\u{2a92}", +        }); +    } + +    if first_char == 'g' && try_read("la;") { +        return Some(CharRef { +            name: "la;", +            characters: "\u{2aa5}", +        }); +    } + +    if first_char == 'g' && try_read("lj;") { +        return Some(CharRef { +            name: "lj;", +            characters: "\u{2aa4}", +        }); +    } + +    if first_char == 'g' && try_read("nE;") { +        return Some(CharRef { +            name: "nE;", +            characters: "\u{2269}", +        }); +    } + +    if first_char == 'g' && try_read("ne;") { +        return Some(CharRef { +            name: "ne;", +            characters: "\u{2a88}", +        }); +    } + +    if first_char == 'h' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d525}", +        }); +    } + +    if first_char == 'i' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{438}", +        }); +    } + +    if first_char == 'i' && try_read("ff;") { +        return Some(CharRef { +            name: "ff;", +            characters: "\u{21d4}", +        }); +    } + +    if first_char == 'i' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d526}", +        }); +    } + +    if first_char == 'i' && try_read("nt;") { +        return Some(CharRef { +            name: "nt;", +            characters: "\u{222b}", +        }); +    } + +    if first_char == 'i' && try_read("uml") { +        return Some(CharRef { +            name: "uml", +            characters: "\u{ef}", +        }); +    } + +    if first_char == 'j' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{439}", +        }); +    } + +    if first_char == 'j' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d527}", +        }); +    } + +    if first_char == 'k' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{43a}", +        }); +    } + +    if first_char == 'k' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d528}", +        }); +    } + +    if first_char == 'l' && try_read("Eg;") { +        return Some(CharRef { +            name: "Eg;", +            characters: "\u{2a8b}", +        }); +    } + +    if first_char == 'l' && try_read("ap;") { +        return Some(CharRef { +            name: "ap;", +            characters: "\u{2a85}", +        }); +    } + +    if first_char == 'l' && try_read("at;") { +        return Some(CharRef { +            name: "at;", +            characters: "\u{2aab}", +        }); +    } + +    if first_char == 'l' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{43b}", +        }); +    } + +    if first_char == 'l' && try_read("eg;") { +        return Some(CharRef { +            name: "eg;", +            characters: "\u{22da}", +        }); +    } + +    if first_char == 'l' && try_read("eq;") { +        return Some(CharRef { +            name: "eq;", +            characters: "\u{2264}", +        }); +    } + +    if first_char == 'l' && try_read("es;") { +        return Some(CharRef { +            name: "es;", +            characters: "\u{2a7d}", +        }); +    } + +    if first_char == 'l' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d529}", +        }); +    } + +    if first_char == 'l' && try_read("gE;") { +        return Some(CharRef { +            name: "gE;", +            characters: "\u{2a91}", +        }); +    } + +    if first_char == 'l' && try_read("nE;") { +        return Some(CharRef { +            name: "nE;", +            characters: "\u{2268}", +        }); +    } + +    if first_char == 'l' && try_read("ne;") { +        return Some(CharRef { +            name: "ne;", +            characters: "\u{2a87}", +        }); +    } + +    if first_char == 'l' && try_read("oz;") { +        return Some(CharRef { +            name: "oz;", +            characters: "\u{25ca}", +        }); +    } + +    if first_char == 'l' && try_read("rm;") { +        return Some(CharRef { +            name: "rm;", +            characters: "\u{200e}", +        }); +    } + +    if first_char == 'l' && try_read("sh;") { +        return Some(CharRef { +            name: "sh;", +            characters: "\u{21b0}", +        }); +    } + +    if first_char == 'm' && try_read("acr") { +        return Some(CharRef { +            name: "acr", +            characters: "\u{af}", +        }); +    } + +    if first_char == 'm' && try_read("ap;") { +        return Some(CharRef { +            name: "ap;", +            characters: "\u{21a6}", +        }); +    } + +    if first_char == 'm' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{43c}", +        }); +    } + +    if first_char == 'm' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d52a}", +        }); +    } + +    if first_char == 'm' && try_read("ho;") { +        return Some(CharRef { +            name: "ho;", +            characters: "\u{2127}", +        }); +    } + +    if first_char == 'm' && try_read("id;") { +        return Some(CharRef { +            name: "id;", +            characters: "\u{2223}", +        }); +    } + +    if first_char == 'n' && try_read("Gg;") { +        return Some(CharRef { +            name: "Gg;", +            characters: "\u{22d9}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("Gt;") { +        return Some(CharRef { +            name: "Gt;", +            characters: "\u{226b}\u{20d2}", +        }); +    } + +    if first_char == 'n' && try_read("Ll;") { +        return Some(CharRef { +            name: "Ll;", +            characters: "\u{22d8}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("Lt;") { +        return Some(CharRef { +            name: "Lt;", +            characters: "\u{226a}\u{20d2}", +        }); +    } + +    if first_char == 'n' && try_read("ap;") { +        return Some(CharRef { +            name: "ap;", +            characters: "\u{2249}", +        }); +    } + +    if first_char == 'n' && try_read("bsp") { +        return Some(CharRef { +            name: "bsp", +            characters: "\u{a0}", +        }); +    } + +    if first_char == 'n' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{43d}", +        }); +    } + +    if first_char == 'n' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d52b}", +        }); +    } + +    if first_char == 'n' && try_read("gE;") { +        return Some(CharRef { +            name: "gE;", +            characters: "\u{2267}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("ge;") { +        return Some(CharRef { +            name: "ge;", +            characters: "\u{2271}", +        }); +    } + +    if first_char == 'n' && try_read("gt;") { +        return Some(CharRef { +            name: "gt;", +            characters: "\u{226f}", +        }); +    } + +    if first_char == 'n' && try_read("is;") { +        return Some(CharRef { +            name: "is;", +            characters: "\u{22fc}", +        }); +    } + +    if first_char == 'n' && try_read("iv;") { +        return Some(CharRef { +            name: "iv;", +            characters: "\u{220b}", +        }); +    } + +    if first_char == 'n' && try_read("lE;") { +        return Some(CharRef { +            name: "lE;", +            characters: "\u{2266}\u{338}", +        }); +    } + +    if first_char == 'n' && try_read("le;") { +        return Some(CharRef { +            name: "le;", +            characters: "\u{2270}", +        }); +    } + +    if first_char == 'n' && try_read("lt;") { +        return Some(CharRef { +            name: "lt;", +            characters: "\u{226e}", +        }); +    } + +    if first_char == 'n' && try_read("ot;") { +        return Some(CharRef { +            name: "ot;", +            characters: "\u{ac}", +        }); +    } + +    if first_char == 'n' && try_read("pr;") { +        return Some(CharRef { +            name: "pr;", +            characters: "\u{2280}", +        }); +    } + +    if first_char == 'n' && try_read("sc;") { +        return Some(CharRef { +            name: "sc;", +            characters: "\u{2281}", +        }); +    } + +    if first_char == 'n' && try_read("um;") { +        return Some(CharRef { +            name: "um;", +            characters: "\u{23}", +        }); +    } + +    if first_char == 'o' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{43e}", +        }); +    } + +    if first_char == 'o' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d52c}", +        }); +    } + +    if first_char == 'o' && try_read("gt;") { +        return Some(CharRef { +            name: "gt;", +            characters: "\u{29c1}", +        }); +    } + +    if first_char == 'o' && try_read("hm;") { +        return Some(CharRef { +            name: "hm;", +            characters: "\u{3a9}", +        }); +    } + +    if first_char == 'o' && try_read("lt;") { +        return Some(CharRef { +            name: "lt;", +            characters: "\u{29c0}", +        }); +    } + +    if first_char == 'o' && try_read("rd;") { +        return Some(CharRef { +            name: "rd;", +            characters: "\u{2a5d}", +        }); +    } + +    if first_char == 'o' && try_read("rdf") { +        return Some(CharRef { +            name: "rdf", +            characters: "\u{aa}", +        }); +    } + +    if first_char == 'o' && try_read("rdm") { +        return Some(CharRef { +            name: "rdm", +            characters: "\u{ba}", +        }); +    } + +    if first_char == 'o' && try_read("rv;") { +        return Some(CharRef { +            name: "rv;", +            characters: "\u{2a5b}", +        }); +    } + +    if first_char == 'o' && try_read("uml") { +        return Some(CharRef { +            name: "uml", +            characters: "\u{f6}", +        }); +    } + +    if first_char == 'p' && try_read("ar;") { +        return Some(CharRef { +            name: "ar;", +            characters: "\u{2225}", +        }); +    } + +    if first_char == 'p' && try_read("ara") { +        return Some(CharRef { +            name: "ara", +            characters: "\u{b6}", +        }); +    } + +    if first_char == 'p' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{43f}", +        }); +    } + +    if first_char == 'p' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d52d}", +        }); +    } + +    if first_char == 'p' && try_read("hi;") { +        return Some(CharRef { +            name: "hi;", +            characters: "\u{3c6}", +        }); +    } + +    if first_char == 'p' && try_read("iv;") { +        return Some(CharRef { +            name: "iv;", +            characters: "\u{3d6}", +        }); +    } + +    if first_char == 'p' && try_read("rE;") { +        return Some(CharRef { +            name: "rE;", +            characters: "\u{2ab3}", +        }); +    } + +    if first_char == 'p' && try_read("re;") { +        return Some(CharRef { +            name: "re;", +            characters: "\u{2aaf}", +        }); +    } + +    if first_char == 'p' && try_read("si;") { +        return Some(CharRef { +            name: "si;", +            characters: "\u{3c8}", +        }); +    } + +    if first_char == 'q' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d52e}", +        }); +    } + +    if first_char == 'q' && try_read("uot") { +        return Some(CharRef { +            name: "uot", +            characters: "\u{22}", +        }); +    } + +    if first_char == 'r' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{440}", +        }); +    } + +    if first_char == 'r' && try_read("eg;") { +        return Some(CharRef { +            name: "eg;", +            characters: "\u{ae}", +        }); +    } + +    if first_char == 'r' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d52f}", +        }); +    } + +    if first_char == 'r' && try_read("ho;") { +        return Some(CharRef { +            name: "ho;", +            characters: "\u{3c1}", +        }); +    } + +    if first_char == 'r' && try_read("lm;") { +        return Some(CharRef { +            name: "lm;", +            characters: "\u{200f}", +        }); +    } + +    if first_char == 'r' && try_read("sh;") { +        return Some(CharRef { +            name: "sh;", +            characters: "\u{21b1}", +        }); +    } + +    if first_char == 's' && try_read("cE;") { +        return Some(CharRef { +            name: "cE;", +            characters: "\u{2ab4}", +        }); +    } + +    if first_char == 's' && try_read("ce;") { +        return Some(CharRef { +            name: "ce;", +            characters: "\u{2ab0}", +        }); +    } + +    if first_char == 's' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{441}", +        }); +    } + +    if first_char == 's' && try_read("ect") { +        return Some(CharRef { +            name: "ect", +            characters: "\u{a7}", +        }); +    } + +    if first_char == 's' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d530}", +        }); +    } + +    if first_char == 's' && try_read("hy;") { +        return Some(CharRef { +            name: "hy;", +            characters: "\u{ad}", +        }); +    } + +    if first_char == 's' && try_read("im;") { +        return Some(CharRef { +            name: "im;", +            characters: "\u{223c}", +        }); +    } + +    if first_char == 's' && try_read("mt;") { +        return Some(CharRef { +            name: "mt;", +            characters: "\u{2aaa}", +        }); +    } + +    if first_char == 's' && try_read("ol;") { +        return Some(CharRef { +            name: "ol;", +            characters: "\u{2f}", +        }); +    } + +    if first_char == 's' && try_read("qu;") { +        return Some(CharRef { +            name: "qu;", +            characters: "\u{25a1}", +        }); +    } + +    if first_char == 's' && try_read("ub;") { +        return Some(CharRef { +            name: "ub;", +            characters: "\u{2282}", +        }); +    } + +    if first_char == 's' && try_read("um;") { +        return Some(CharRef { +            name: "um;", +            characters: "\u{2211}", +        }); +    } + +    if first_char == 's' && try_read("up1") { +        return Some(CharRef { +            name: "up1", +            characters: "\u{b9}", +        }); +    } + +    if first_char == 's' && try_read("up2") { +        return Some(CharRef { +            name: "up2", +            characters: "\u{b2}", +        }); +    } + +    if first_char == 's' && try_read("up3") { +        return Some(CharRef { +            name: "up3", +            characters: "\u{b3}", +        }); +    } + +    if first_char == 's' && try_read("up;") { +        return Some(CharRef { +            name: "up;", +            characters: "\u{2283}", +        }); +    } + +    if first_char == 't' && try_read("au;") { +        return Some(CharRef { +            name: "au;", +            characters: "\u{3c4}", +        }); +    } + +    if first_char == 't' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{442}", +        }); +    } + +    if first_char == 't' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d531}", +        }); +    } + +    if first_char == 't' && try_read("op;") { +        return Some(CharRef { +            name: "op;", +            characters: "\u{22a4}", +        }); +    } + +    if first_char == 'u' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{443}", +        }); +    } + +    if first_char == 'u' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d532}", +        }); +    } + +    if first_char == 'u' && try_read("ml;") { +        return Some(CharRef { +            name: "ml;", +            characters: "\u{a8}", +        }); +    } + +    if first_char == 'u' && try_read("uml") { +        return Some(CharRef { +            name: "uml", +            characters: "\u{fc}", +        }); +    } + +    if first_char == 'v' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{432}", +        }); +    } + +    if first_char == 'v' && try_read("ee;") { +        return Some(CharRef { +            name: "ee;", +            characters: "\u{2228}", +        }); +    } + +    if first_char == 'v' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d533}", +        }); +    } + +    if first_char == 'w' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d534}", +        }); +    } + +    if first_char == 'x' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d535}", +        }); +    } + +    if first_char == 'y' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{44b}", +        }); +    } + +    if first_char == 'y' && try_read("en;") { +        return Some(CharRef { +            name: "en;", +            characters: "\u{a5}", +        }); +    } + +    if first_char == 'y' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d536}", +        }); +    } + +    if first_char == 'y' && try_read("uml") { +        return Some(CharRef { +            name: "uml", +            characters: "\u{ff}", +        }); +    } + +    if first_char == 'z' && try_read("cy;") { +        return Some(CharRef { +            name: "cy;", +            characters: "\u{437}", +        }); +    } + +    if first_char == 'z' && try_read("fr;") { +        return Some(CharRef { +            name: "fr;", +            characters: "\u{1d537}", +        }); +    } + +    if first_char == 'z' && try_read("wj;") { +        return Some(CharRef { +            name: "wj;", +            characters: "\u{200d}", +        }); +    } + +    if first_char == 'A' && try_read("MP") { +        return Some(CharRef { +            name: "MP", +            characters: "\u{26}", +        }); +    } + +    if first_char == 'D' && try_read("D;") { +        return Some(CharRef { +            name: "D;", +            characters: "\u{2145}", +        }); +    } + +    if first_char == 'E' && try_read("TH") { +        return Some(CharRef { +            name: "TH", +            characters: "\u{d0}", +        }); +    } + +    if first_char == 'G' && try_read("T;") { +        return Some(CharRef { +            name: "T;", +            characters: "\u{3e}", +        }); +    } + +    if first_char == 'G' && try_read("g;") { +        return Some(CharRef { +            name: "g;", +            characters: "\u{22d9}", +        }); +    } + +    if first_char == 'G' && try_read("t;") { +        return Some(CharRef { +            name: "t;", +            characters: "\u{226b}", +        }); +    } + +    if first_char == 'I' && try_read("m;") { +        return Some(CharRef { +            name: "m;", +            characters: "\u{2111}", +        }); +    } + +    if first_char == 'L' && try_read("T;") { +        return Some(CharRef { +            name: "T;", +            characters: "\u{3c}", +        }); +    } + +    if first_char == 'L' && try_read("l;") { +        return Some(CharRef { +            name: "l;", +            characters: "\u{22d8}", +        }); +    } + +    if first_char == 'L' && try_read("t;") { +        return Some(CharRef { +            name: "t;", +            characters: "\u{226a}", +        }); +    } + +    if first_char == 'M' && try_read("u;") { +        return Some(CharRef { +            name: "u;", +            characters: "\u{39c}", +        }); +    } + +    if first_char == 'N' && try_read("u;") { +        return Some(CharRef { +            name: "u;", +            characters: "\u{39d}", +        }); +    } + +    if first_char == 'O' && try_read("r;") { +        return Some(CharRef { +            name: "r;", +            characters: "\u{2a54}", +        }); +    } + +    if first_char == 'P' && try_read("i;") { +        return Some(CharRef { +            name: "i;", +            characters: "\u{3a0}", +        }); +    } + +    if first_char == 'P' && try_read("r;") { +        return Some(CharRef { +            name: "r;", +            characters: "\u{2abb}", +        }); +    } + +    if first_char == 'R' && try_read("EG") { +        return Some(CharRef { +            name: "EG", +            characters: "\u{ae}", +        }); +    } + +    if first_char == 'R' && try_read("e;") { +        return Some(CharRef { +            name: "e;", +            characters: "\u{211c}", +        }); +    } + +    if first_char == 'S' && try_read("c;") { +        return Some(CharRef { +            name: "c;", +            characters: "\u{2abc}", +        }); +    } + +    if first_char == 'X' && try_read("i;") { +        return Some(CharRef { +            name: "i;", +            characters: "\u{39e}", +        }); +    } + +    if first_char == 'a' && try_read("c;") { +        return Some(CharRef { +            name: "c;", +            characters: "\u{223e}", +        }); +    } + +    if first_char == 'a' && try_read("f;") { +        return Some(CharRef { +            name: "f;", +            characters: "\u{2061}", +        }); +    } + +    if first_char == 'a' && try_read("mp") { +        return Some(CharRef { +            name: "mp", +            characters: "\u{26}", +        }); +    } + +    if first_char == 'a' && try_read("p;") { +        return Some(CharRef { +            name: "p;", +            characters: "\u{2248}", +        }); +    } + +    if first_char == 'd' && try_read("d;") { +        return Some(CharRef { +            name: "d;", +            characters: "\u{2146}", +        }); +    } + +    if first_char == 'd' && try_read("eg") { +        return Some(CharRef { +            name: "eg", +            characters: "\u{b0}", +        }); +    } + +    if first_char == 'e' && try_read("e;") { +        return Some(CharRef { +            name: "e;", +            characters: "\u{2147}", +        }); +    } + +    if first_char == 'e' && try_read("g;") { +        return Some(CharRef { +            name: "g;", +            characters: "\u{2a9a}", +        }); +    } + +    if first_char == 'e' && try_read("l;") { +        return Some(CharRef { +            name: "l;", +            characters: "\u{2a99}", +        }); +    } + +    if first_char == 'e' && try_read("th") { +        return Some(CharRef { +            name: "th", +            characters: "\u{f0}", +        }); +    } + +    if first_char == 'g' && try_read("E;") { +        return Some(CharRef { +            name: "E;", +            characters: "\u{2267}", +        }); +    } + +    if first_char == 'g' && try_read("e;") { +        return Some(CharRef { +            name: "e;", +            characters: "\u{2265}", +        }); +    } + +    if first_char == 'g' && try_read("g;") { +        return Some(CharRef { +            name: "g;", +            characters: "\u{226b}", +        }); +    } + +    if first_char == 'g' && try_read("l;") { +        return Some(CharRef { +            name: "l;", +            characters: "\u{2277}", +        }); +    } + +    if first_char == 'g' && try_read("t;") { +        return Some(CharRef { +            name: "t;", +            characters: "\u{3e}", +        }); +    } + +    if first_char == 'i' && try_read("c;") { +        return Some(CharRef { +            name: "c;", +            characters: "\u{2063}", +        }); +    } + +    if first_char == 'i' && try_read("i;") { +        return Some(CharRef { +            name: "i;", +            characters: "\u{2148}", +        }); +    } + +    if first_char == 'i' && try_read("n;") { +        return Some(CharRef { +            name: "n;", +            characters: "\u{2208}", +        }); +    } + +    if first_char == 'i' && try_read("t;") { +        return Some(CharRef { +            name: "t;", +            characters: "\u{2062}", +        }); +    } + +    if first_char == 'l' && try_read("E;") { +        return Some(CharRef { +            name: "E;", +            characters: "\u{2266}", +        }); +    } + +    if first_char == 'l' && try_read("e;") { +        return Some(CharRef { +            name: "e;", +            characters: "\u{2264}", +        }); +    } + +    if first_char == 'l' && try_read("g;") { +        return Some(CharRef { +            name: "g;", +            characters: "\u{2276}", +        }); +    } + +    if first_char == 'l' && try_read("l;") { +        return Some(CharRef { +            name: "l;", +            characters: "\u{226a}", +        }); +    } + +    if first_char == 'l' && try_read("t;") { +        return Some(CharRef { +            name: "t;", +            characters: "\u{3c}", +        }); +    } + +    if first_char == 'm' && try_read("p;") { +        return Some(CharRef { +            name: "p;", +            characters: "\u{2213}", +        }); +    } + +    if first_char == 'm' && try_read("u;") { +        return Some(CharRef { +            name: "u;", +            characters: "\u{3bc}", +        }); +    } + +    if first_char == 'n' && try_read("e;") { +        return Some(CharRef { +            name: "e;", +            characters: "\u{2260}", +        }); +    } + +    if first_char == 'n' && try_read("i;") { +        return Some(CharRef { +            name: "i;", +            characters: "\u{220b}", +        }); +    } + +    if first_char == 'n' && try_read("ot") { +        return Some(CharRef { +            name: "ot", +            characters: "\u{ac}", +        }); +    } + +    if first_char == 'n' && try_read("u;") { +        return Some(CharRef { +            name: "u;", +            characters: "\u{3bd}", +        }); +    } + +    if first_char == 'o' && try_read("S;") { +        return Some(CharRef { +            name: "S;", +            characters: "\u{24c8}", +        }); +    } + +    if first_char == 'o' && try_read("r;") { +        return Some(CharRef { +            name: "r;", +            characters: "\u{2228}", +        }); +    } + +    if first_char == 'p' && try_read("i;") { +        return Some(CharRef { +            name: "i;", +            characters: "\u{3c0}", +        }); +    } + +    if first_char == 'p' && try_read("m;") { +        return Some(CharRef { +            name: "m;", +            characters: "\u{b1}", +        }); +    } + +    if first_char == 'p' && try_read("r;") { +        return Some(CharRef { +            name: "r;", +            characters: "\u{227a}", +        }); +    } + +    if first_char == 'r' && try_read("eg") { +        return Some(CharRef { +            name: "eg", +            characters: "\u{ae}", +        }); +    } + +    if first_char == 'r' && try_read("x;") { +        return Some(CharRef { +            name: "x;", +            characters: "\u{211e}", +        }); +    } + +    if first_char == 's' && try_read("c;") { +        return Some(CharRef { +            name: "c;", +            characters: "\u{227b}", +        }); +    } + +    if first_char == 's' && try_read("hy") { +        return Some(CharRef { +            name: "hy", +            characters: "\u{ad}", +        }); +    } + +    if first_char == 'u' && try_read("ml") { +        return Some(CharRef { +            name: "ml", +            characters: "\u{a8}", +        }); +    } + +    if first_char == 'w' && try_read("p;") { +        return Some(CharRef { +            name: "p;", +            characters: "\u{2118}", +        }); +    } + +    if first_char == 'w' && try_read("r;") { +        return Some(CharRef { +            name: "r;", +            characters: "\u{2240}", +        }); +    } + +    if first_char == 'x' && try_read("i;") { +        return Some(CharRef { +            name: "i;", +            characters: "\u{3be}", +        }); +    } + +    if first_char == 'y' && try_read("en") { +        return Some(CharRef { +            name: "en", +            characters: "\u{a5}", +        }); +    } + +    if first_char == 'G' && try_read("T") { +        return Some(CharRef { +            name: "T", +            characters: "\u{3e}", +        }); +    } + +    if first_char == 'L' && try_read("T") { +        return Some(CharRef { +            name: "T", +            characters: "\u{3c}", +        }); +    } + +    if first_char == 'g' && try_read("t") { +        return Some(CharRef { +            name: "t", +            characters: "\u{3e}", +        }); +    } + +    if first_char == 'l' && try_read("t") { +        return Some(CharRef { +            name: "t", +            characters: "\u{3c}", +        }); +    } +    None +} diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..6090fdf --- /dev/null +++ b/src/error.rs @@ -0,0 +1,87 @@ +macro_rules! impl_error { +    ($( +        $string:literal <=> $variant:ident, +    )*) => { +        /// All [parsing errors](https://html.spec.whatwg.org/#parse-errors) this tokenizer can emit. +        #[derive(Debug, Eq, PartialEq)] +        pub enum Error { +            $( +                #[doc = "This error corresponds to the `$literal` error found in the WHATWG spec."] +                $variant +            ),* +        } +        impl std::str::FromStr for Error { +            type Err = (); + +            /// Parse a `kebap-case` error code as typically written in the WHATWG spec into an +            /// enum variant. +            fn from_str(s: &str) -> Result<Self, Self::Err> { +                match s { +                    $( $string => Ok(Self::$variant), )* +                    _ => Err(()) +                } +            } +        } + +        impl std::fmt::Display for Error { +            /// Convert an enum variant back into the `kebap-case` error code as typically written +            /// in the WHATWG spec. +            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +                match *self { +                    $( Self::$variant => $string.fmt(f), )* +                } +            } +        } +    } +} + +impl_error! { +    "abrupt-closing-of-empty-comment" <=> AbruptClosingOfEmptyComment, +    "abrupt-doctype-public-identifier" <=> AbruptDoctypePublicIdentifier, +    "abrupt-doctype-system-identifier" <=> AbruptDoctypeSystemIdentifier, +    "absence-of-digits-in-numeric-character-reference" <=> AbsenceOfDigitsInNumericCharacterReference, +    "cdata-in-html-content" <=> CdataInHtmlContent, +    "character-reference-outside-unicode-range" <=> CharacterReferenceOutsideUnicodeRange, +    "control-character-reference" <=> ControlCharacterReference, +    "end-tag-with-attributes" <=> EndTagWithAttributes, +    "end-tag-with-trailing-solidus" <=> EndTagWithTrailingSolidus, +    "eof-before-tag-name" <=> EofBeforeTagName, +    "eof-in-cdata" <=> EofInCdata, +    "eof-in-comment" <=> EofInComment, +    "eof-in-doctype" <=> EofInDoctype, +    "eof-in-script-html-comment-like-text" <=> EofInScriptHtmlCommentLikeText, +    "eof-in-tag" <=> EofInTag, +    "incorrectly-closed-comment" <=> IncorrectlyClosedComment, +    "incorrectly-opened-comment" <=> IncorrectlyOpenedComment, +    "invalid-character-sequence-after-doctype-name" <=> InvalidCharacterSequenceAfterDoctypeName, +    "invalid-first-character-of-tag-name" <=> InvalidFirstCharacterOfTagName, +    "missing-attribute-value" <=> MissingAttributeValue, +    "missing-doctype-name" <=> MissingDoctypeName, +    "missing-doctype-public-identifier" <=> MissingDoctypePublicIdentifier, +    "missing-doctype-system-identifier" <=> MissingDoctypeSystemIdentifier, +    "missing-end-tag-name" <=> MissingEndTagName, +    "missing-quote-before-doctype-public-identifier" <=> MissingQuoteBeforeDoctypePublicIdentifier, +    "missing-quote-before-doctype-system-identifier" <=> MissingQuoteBeforeDoctypeSystemIdentifier, +    "missing-semicolon-after-character-reference" <=> MissingSemicolonAfterCharacterReference, +    "missing-whitespace-after-doctype-public-keyword" <=> MissingWhitespaceAfterDoctypePublicKeyword, +    "missing-whitespace-after-doctype-system-keyword" <=> MissingWhitespaceAfterDoctypeSystemKeyword, +    "missing-whitespace-before-doctype-name" <=> MissingWhitespaceBeforeDoctypeName, +    "missing-whitespace-between-attributes" <=> MissingWhitespaceBetweenAttributes, +    "missing-whitespace-between-doctype-public-and-system-identifiers" <=> MissingWhitespaceBetweenDoctypePublicAndSystemIdentifiers, +    "nested-comment" <=> NestedComment, +    "noncharacter-character-reference" <=> NoncharacterCharacterReference, +    "noncharacter-in-input-stream" <=> NoncharacterInInputStream, +    "null-character-reference" <=> NullCharacterReference, +    "surrogate-character-reference" <=> SurrogateCharacterReference, +    "surrogate-in-input-stream" <=> SurrogateInInputStream, +    "unexpected-character-after-doctype-system-identifier" <=> UnexpectedCharacterAfterDoctypeSystemIdentifier, +    "unexpected-character-in-attribute-name" <=> UnexpectedCharacterInAttributeName, +    "unexpected-character-in-unquoted-attribute-value" <=> UnexpectedCharacterInUnquotedAttributeValue, +    "unexpected-equals-sign-before-attribute-name" <=> UnexpectedEqualsSignBeforeAttributeName, +    "unexpected-null-character" <=> UnexpectedNullCharacter, +    "unexpected-question-mark-instead-of-tag-name" <=> UnexpectedQuestionMarkInsteadOfTagName, +    "unexpected-solidus-in-tag" <=> UnexpectedSolidusInTag, +    "unknown-named-character-reference" <=> UnknownNamedCharacterReference, +    "duplicate-attribute" <=> DuplicateAttribute, +    "control-character-in-input-stream" <=> ControlCharacterInInputStream, +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..ef6c9a2 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,2112 @@ +#![deny(missing_docs)] +// This is an HTML parser. HTML can be untrusted input from the internet. +#![forbid(unsafe_code)] +#![doc = include_str!("../README.md")] + +mod emitter; +mod entities; +mod error; +mod machine; +mod reader; + +#[cfg(feature = "integration-tests")] +pub use machine::State; +#[cfg(not(feature = "integration-tests"))] +use machine::State; + +use machine::{ +    ascii_digit_pat, control_pat, noncharacter_pat, surrogate_pat, whitespace_pat, ControlToken, +}; + +pub use emitter::{DefaultEmitter, Doctype, Emitter, EndTag, StartTag, Token}; +pub use reader::{Readable, Reader, StringReader}; + +pub use error::Error; + +macro_rules! ctostr { +    ($c:expr) => { +        &*$c.encode_utf8(&mut [0; 4]) +    }; +} + +/// A HTML tokenizer. See crate-level docs for basic usage. +pub struct Tokenizer<R: Reader, E: Emitter = DefaultEmitter> { +    eof: bool, +    state: State, +    emitter: E, +    temporary_buffer: String, +    reader: R, +    to_reconsume: Option<Option<char>>, +    character_reference_code: u32, +    return_state: Option<State>, +} + +impl<R: Reader> Tokenizer<R> { +    /// Create a new tokenizer from some input. +    /// +    /// `input` can be `&String` or `&str` at the moment, as those are the types for which +    /// [`crate::Readable`] is implemented, but you can implement that trait on your own types. +    /// +    /// Patches are welcome for providing an efficient implementation over async streams, +    /// iterators, files, etc, as long as any dependencies come behind featureflags. +    pub fn new<'a, S: Readable<'a, Reader = R>>(input: S) -> Self { +        Tokenizer::<S::Reader>::new_with_emitter(input, DefaultEmitter::default()) +    } +} + +impl<R: Reader, E: Emitter> Tokenizer<R, E> { +    /// Construct a new tokenizer from some input and a custom emitter. +    /// +    /// Use this method over [`Tokenizer::new`] when you want to have more control over string allocation for +    /// tokens. +    pub fn new_with_emitter<'a, S: Readable<'a, Reader = R>>(input: S, emitter: E) -> Self { +        Tokenizer { +            eof: false, +            state: State::Data, +            emitter, +            temporary_buffer: String::new(), +            to_reconsume: None, +            reader: input.to_reader(), +            character_reference_code: 0, +            return_state: None, +        } +    } + +    #[cfg(feature = "integration-tests")] +    /// Test-internal function to override internal state. +    /// +    /// Only available with the `integration-tests` feature which is not public API. +    pub fn set_state(&mut self, state: State) { +        self.state = state; +    } + +    /// Set the statemachine to start/continue in [plaintext +    /// state](https://html.spec.whatwg.org/#plaintext-state). +    /// +    /// This tokenizer never gets into that state naturally. +    pub fn set_plaintext_state(&mut self) { +        self.state = State::PlainText; +    } + +    #[cfg(feature = "integration-tests")] +    /// Test-internal function to override internal state. +    /// +    /// Only available with the `integration-tests` feature which is not public API. +    pub fn set_last_start_tag(&mut self, last_start_tag: Option<&str>) { +        self.emitter.set_last_start_tag(last_start_tag); +    } + +    #[inline] +    fn unread_char(&mut self, c: Option<char>) { +        self.to_reconsume = Some(c); +    } + +    #[inline] +    fn validate_char(&mut self, c: char) { +        match c as u32 { +            surrogate_pat!() => { +                self.emitter.emit_error(Error::SurrogateInInputStream); +            } +            noncharacter_pat!() => { +                self.emitter.emit_error(Error::NoncharacterInInputStream); +            } +            // control without whitespace or nul +            x @ control_pat!() +                if !matches!(x, 0x0000 | 0x0009 | 0x000a | 0x000c | 0x000d | 0x0020) => +            { +                self.emitter +                    .emit_error(Error::ControlCharacterInInputStream); +            } +            _ => (), +        } +    } + +    fn read_char(&mut self) -> Option<char> { +        if let Some(c) = self.to_reconsume.take() { +            return c; +        } + +        let c = self.reader.read_char()?; +        self.validate_char(c); +        Some(c) +    } + +    #[inline] +    fn try_read_string(&mut self, s: &str, case_sensitive: bool) -> bool { +        debug_assert!(!s.is_empty()); +        debug_assert!(self.to_reconsume.is_none()); +        self.reader.try_read_string(s, case_sensitive) +    } + +    fn is_consumed_as_part_of_an_attribute(&self) -> bool { +        matches!( +            self.return_state, +            Some( +                State::AttributeValueDoubleQuoted +                    | State::AttributeValueSingleQuoted +                    | State::AttributeValueUnquoted +            ) +        ) +    } + +    fn flush_code_points_consumed_as_character_reference(&mut self) { +        if self.is_consumed_as_part_of_an_attribute() { +            self.emitter.push_attribute_value(&self.temporary_buffer); +            self.temporary_buffer.clear(); +        } else { +            self.flush_buffer_characters(); +        } +    } + +    fn next_input_character(&mut self) -> Option<char> { +        let rv = self.read_char(); +        self.unread_char(rv); +        rv +    } + +    fn flush_buffer_characters(&mut self) { +        self.emitter.emit_string(&self.temporary_buffer); +        self.temporary_buffer.clear(); +    } + +    fn consume(&mut self) -> ControlToken { +        macro_rules! mutate_character_reference { +            (* $mul:literal + $x:ident - $sub:literal) => { +                match self +                    .character_reference_code +                    .checked_mul($mul) +                    .and_then(|cr| cr.checked_add($x as u32 - $sub)) +                { +                    Some(cr) => self.character_reference_code = cr, +                    None => { +                        // provoke err +                        self.character_reference_code = 0x110000; +                    } +                }; +            }; +        } + +        match self.state { +            State::Data => match self.read_char() { +                Some('&') => { +                    self.return_state = Some(self.state); +                    self.state = State::CharacterReference; +                    ControlToken::Continue +                } +                Some('<') => { +                    self.state = State::TagOpen; +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.emit_string("\0"); +                    ControlToken::Continue +                } +                Some(x) => { +                    self.emitter.emit_string(ctostr!(x)); +                    ControlToken::Continue +                } +                None => ControlToken::Eof, +            }, +            State::RcData => match self.read_char() { +                Some('&') => { +                    self.return_state = Some(State::RcData); +                    self.state = State::CharacterReference; +                    ControlToken::Continue +                } +                Some('<') => { +                    self.state = State::RcDataLessThanSign; +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.emit_string("\u{fffd}"); +                    ControlToken::Continue +                } +                Some(x) => { +                    self.emitter.emit_string(ctostr!(x)); +                    ControlToken::Continue +                } +                None => ControlToken::Eof, +            }, +            State::RawText => match self.read_char() { +                Some('<') => { +                    self.state = State::RawTextLessThanSign; +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.emit_string("\u{fffd}"); +                    ControlToken::Continue +                } +                Some(x) => { +                    self.emitter.emit_string(ctostr!(x)); +                    ControlToken::Continue +                } +                None => ControlToken::Eof, +            }, +            State::ScriptData => match self.read_char() { +                Some('<') => { +                    self.state = State::ScriptDataLessThanSign; +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.emit_string("\u{fffd}"); +                    ControlToken::Continue +                } +                Some(x) => { +                    self.emitter.emit_string(ctostr!(x)); +                    ControlToken::Continue +                } +                None => ControlToken::Eof, +            }, +            State::PlainText => match self.read_char() { +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.emit_string("\u{fffd}"); +                    ControlToken::Continue +                } +                Some(x) => { +                    self.emitter.emit_string(ctostr!(x)); +                    ControlToken::Continue +                } +                None => ControlToken::Eof, +            }, +            State::TagOpen => match self.read_char() { +                Some('!') => { +                    self.state = State::MarkupDeclarationOpen; +                    ControlToken::Continue +                } +                Some('/') => { +                    self.state = State::EndTagOpen; +                    ControlToken::Continue +                } +                Some(x) if x.is_ascii_alphabetic() => { +                    self.emitter.init_start_tag(); +                    self.state = State::TagName; +                    self.unread_char(Some(x)); +                    ControlToken::Continue +                } +                c @ Some('?') => { +                    self.emitter +                        .emit_error(Error::UnexpectedQuestionMarkInsteadOfTagName); +                    self.emitter.init_comment(); +                    self.state = State::BogusComment; +                    self.unread_char(c); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofBeforeTagName); +                    self.emitter.emit_string("<"); +                    ControlToken::Eof +                } +                c @ Some(_) => { +                    self.emitter +                        .emit_error(Error::InvalidFirstCharacterOfTagName); +                    self.state = State::Data; +                    self.emitter.emit_string("<"); +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::EndTagOpen => match self.read_char() { +                Some(x) if x.is_ascii_alphabetic() => { +                    self.emitter.init_end_tag(); +                    self.state = State::TagName; +                    self.unread_char(Some(x)); +                    ControlToken::Continue +                } +                Some('>') => { +                    self.emitter.emit_error(Error::MissingEndTagName); +                    self.state = State::Data; +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofBeforeTagName); +                    self.emitter.emit_string("</"); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.emitter +                        .emit_error(Error::InvalidFirstCharacterOfTagName); +                    self.emitter.init_comment(); +                    self.state = State::BogusComment; +                    self.unread_char(Some(x)); +                    ControlToken::Continue +                } +            }, +            State::TagName => match self.read_char() { +                Some(whitespace_pat!()) => { +                    self.state = State::BeforeAttributeName; +                    ControlToken::Continue +                } +                Some('/') => { +                    self.state = State::SelfClosingStartTag; +                    ControlToken::Continue +                } +                Some('>') => { +                    self.state = State::Data; +                    self.emitter.emit_current_tag(); +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.push_tag_name("\u{fffd}"); +                    ControlToken::Continue +                } +                Some(x) => { +                    self.emitter.push_tag_name(ctostr!(x.to_ascii_lowercase())); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInTag); +                    ControlToken::Eof +                } +            }, +            State::RcDataLessThanSign => match self.read_char() { +                Some('/') => { +                    self.temporary_buffer.clear(); +                    self.state = State::RcDataEndTagOpen; +                    ControlToken::Continue +                } +                c => { +                    self.emitter.emit_string("<"); +                    self.state = State::RcData; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::RcDataEndTagOpen => match self.read_char() { +                Some(x) if x.is_ascii_alphabetic() => { +                    self.emitter.init_end_tag(); +                    self.state = State::RcDataEndTagName; +                    self.unread_char(Some(x)); +                    ControlToken::Continue +                } +                c => { +                    self.emitter.emit_string("</"); +                    self.state = State::RcData; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::RcDataEndTagName => match self.read_char() { +                Some(whitespace_pat!()) if self.emitter.current_is_appropriate_end_tag_token() => { +                    self.state = State::BeforeAttributeName; +                    ControlToken::Continue +                } +                Some('/') if self.emitter.current_is_appropriate_end_tag_token() => { +                    self.state = State::SelfClosingStartTag; +                    ControlToken::Continue +                } +                Some('>') if self.emitter.current_is_appropriate_end_tag_token() => { +                    self.state = State::Data; +                    self.emitter.emit_current_tag(); +                    ControlToken::Continue +                } +                Some(x) if x.is_ascii_alphabetic() => { +                    self.emitter.push_tag_name(ctostr!(x.to_ascii_lowercase())); +                    self.temporary_buffer.push(x); +                    ControlToken::Continue +                } +                c => { +                    self.emitter.emit_string("</"); +                    self.flush_buffer_characters(); + +                    self.state = State::RcData; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::RawTextLessThanSign => match self.read_char() { +                Some('/') => { +                    self.temporary_buffer.clear(); +                    self.state = State::RawTextEndTagOpen; +                    ControlToken::Continue +                } +                c => { +                    self.emitter.emit_string("<"); +                    self.state = State::RawText; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::RawTextEndTagOpen => match self.read_char() { +                Some(x) if x.is_ascii_alphabetic() => { +                    self.emitter.init_end_tag(); +                    self.state = State::RawTextEndTagName; +                    self.unread_char(Some(x)); +                    ControlToken::Continue +                } +                c => { +                    self.emitter.emit_string("</"); +                    self.state = State::RawText; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::RawTextEndTagName => match self.read_char() { +                Some(whitespace_pat!()) if self.emitter.current_is_appropriate_end_tag_token() => { +                    self.state = State::BeforeAttributeName; +                    ControlToken::Continue +                } +                Some('/') if self.emitter.current_is_appropriate_end_tag_token() => { +                    self.state = State::SelfClosingStartTag; +                    ControlToken::Continue +                } +                Some('>') if self.emitter.current_is_appropriate_end_tag_token() => { +                    self.state = State::Data; +                    self.emitter.emit_current_tag(); +                    ControlToken::Continue +                } +                Some(x) if x.is_ascii_alphabetic() => { +                    self.emitter.push_tag_name(ctostr!(x.to_ascii_lowercase())); +                    self.temporary_buffer.push(x); +                    ControlToken::Continue +                } +                c => { +                    self.emitter.emit_string("</"); +                    self.flush_buffer_characters(); + +                    self.state = State::RawText; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::ScriptDataLessThanSign => match self.read_char() { +                Some('/') => { +                    self.temporary_buffer.clear(); +                    self.state = State::ScriptDataEndTagOpen; +                    ControlToken::Continue +                } +                Some('!') => { +                    self.state = State::ScriptDataEscapeStart; +                    self.emitter.emit_string("<!"); +                    ControlToken::Continue +                } +                c => { +                    self.emitter.emit_string("<"); +                    self.state = State::Data; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::ScriptDataEndTagOpen => match self.read_char() { +                Some(x) if x.is_ascii_alphabetic() => { +                    self.emitter.init_end_tag(); +                    self.state = State::ScriptDataEndTagName; +                    self.unread_char(Some(x)); +                    ControlToken::Continue +                } +                c => { +                    self.emitter.emit_string("</"); +                    self.state = State::ScriptData; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::ScriptDataEndTagName => match self.read_char() { +                Some(whitespace_pat!()) if self.emitter.current_is_appropriate_end_tag_token() => { +                    self.state = State::BeforeAttributeName; +                    ControlToken::Continue +                } +                Some('/') if self.emitter.current_is_appropriate_end_tag_token() => { +                    self.state = State::SelfClosingStartTag; +                    ControlToken::Continue +                } +                Some('>') if self.emitter.current_is_appropriate_end_tag_token() => { +                    self.state = State::Data; +                    self.emitter.emit_current_tag(); +                    ControlToken::Continue +                } +                Some(x) if x.is_ascii_alphabetic() => { +                    self.emitter.push_tag_name(ctostr!(x.to_ascii_lowercase())); +                    self.temporary_buffer.push(x.to_ascii_lowercase()); +                    ControlToken::Continue +                } +                c => { +                    self.emitter.emit_string("</"); +                    self.flush_buffer_characters(); +                    self.state = State::Data; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::ScriptDataEscapeStart => match self.read_char() { +                Some('-') => { +                    self.state = State::ScriptDataEscapeStartDash; +                    self.emitter.emit_string("-"); +                    ControlToken::Continue +                } +                c => { +                    self.state = State::ScriptData; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::ScriptDataEscapeStartDash => match self.read_char() { +                Some('-') => { +                    self.state = State::ScriptDataEscapedDashDash; +                    self.emitter.emit_string("-"); +                    ControlToken::Continue +                } +                c => { +                    self.state = State::ScriptData; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::ScriptDataEscaped => match self.read_char() { +                Some('-') => { +                    self.state = State::ScriptDataEscapedDash; +                    self.emitter.emit_string("-"); +                    ControlToken::Continue +                } +                Some('<') => { +                    self.state = State::ScriptDataEscapedLessThanSign; +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.emit_string("\u{fffd}"); +                    ControlToken::Continue +                } +                None => { +                    self.emitter +                        .emit_error(Error::EofInScriptHtmlCommentLikeText); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.emitter.emit_string(ctostr!(x)); +                    ControlToken::Continue +                } +            }, +            State::ScriptDataEscapedDash => match self.read_char() { +                Some('-') => { +                    self.state = State::ScriptDataEscapedDashDash; +                    self.emitter.emit_string("-"); +                    ControlToken::Continue +                } +                Some('<') => { +                    self.state = State::ScriptDataEscapedLessThanSign; +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.state = State::ScriptDataEscaped; +                    self.emitter.emit_string("\u{fffd}"); +                    ControlToken::Continue +                } +                None => { +                    self.emitter +                        .emit_error(Error::EofInScriptHtmlCommentLikeText); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.state = State::ScriptDataEscaped; +                    self.emitter.emit_string(ctostr!(x)); +                    ControlToken::Continue +                } +            }, +            State::ScriptDataEscapedDashDash => match self.read_char() { +                Some('-') => { +                    self.emitter.emit_string("-"); +                    ControlToken::Continue +                } +                Some('<') => { +                    self.state = State::ScriptDataEscapedLessThanSign; +                    ControlToken::Continue +                } +                Some('>') => { +                    self.state = State::ScriptData; +                    self.emitter.emit_string(">"); +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.state = State::ScriptDataEscaped; +                    self.emitter.emit_string("\u{fffd}"); +                    ControlToken::Continue +                } +                None => { +                    self.emitter +                        .emit_error(Error::EofInScriptHtmlCommentLikeText); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.state = State::ScriptDataEscaped; +                    self.emitter.emit_string(ctostr!(x)); +                    ControlToken::Continue +                } +            }, +            State::ScriptDataEscapedLessThanSign => match self.read_char() { +                Some('/') => { +                    self.temporary_buffer.clear(); +                    self.state = State::ScriptDataEscapedEndTagOpen; +                    ControlToken::Continue +                } +                Some(x) if x.is_ascii_alphabetic() => { +                    self.temporary_buffer.clear(); +                    self.emitter.emit_string("<"); +                    self.state = State::ScriptDataDoubleEscapeStart; +                    self.unread_char(Some(x)); +                    ControlToken::Continue +                } +                c => { +                    self.emitter.emit_string("<"); +                    self.state = State::ScriptDataEscaped; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::ScriptDataEscapedEndTagOpen => match self.read_char() { +                Some(x) if x.is_ascii_alphabetic() => { +                    self.emitter.init_end_tag(); +                    self.state = State::ScriptDataEscapedEndTagName; +                    self.unread_char(Some(x)); +                    ControlToken::Continue +                } +                c => { +                    self.emitter.emit_string("</"); +                    self.unread_char(c); +                    self.state = State::ScriptDataEscaped; +                    ControlToken::Continue +                } +            }, +            State::ScriptDataEscapedEndTagName => match self.read_char() { +                Some(whitespace_pat!()) if self.emitter.current_is_appropriate_end_tag_token() => { +                    self.state = State::BeforeAttributeName; +                    ControlToken::Continue +                } +                Some('/') if self.emitter.current_is_appropriate_end_tag_token() => { +                    self.state = State::SelfClosingStartTag; +                    ControlToken::Continue +                } +                Some('>') if self.emitter.current_is_appropriate_end_tag_token() => { +                    self.state = State::Data; +                    self.emitter.emit_current_tag(); +                    ControlToken::Continue +                } +                Some(x) if x.is_ascii_alphabetic() => { +                    self.emitter.push_tag_name(ctostr!(x.to_ascii_lowercase())); +                    self.temporary_buffer.push(x); +                    ControlToken::Continue +                } +                c => { +                    self.emitter.emit_string("</"); +                    self.flush_buffer_characters(); +                    self.state = State::ScriptDataEscaped; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::ScriptDataDoubleEscapeStart => match self.read_char() { +                Some(x @ whitespace_pat!() | x @ '/' | x @ '>') => { +                    if self.temporary_buffer == "script" { +                        self.state = State::ScriptDataDoubleEscaped; +                    } else { +                        self.state = State::ScriptDataEscaped; +                    } +                    self.emitter.emit_string(ctostr!(x)); +                    ControlToken::Continue +                } +                Some(x) if x.is_ascii_alphabetic() => { +                    self.temporary_buffer.push(x.to_ascii_lowercase()); +                    self.emitter.emit_string(ctostr!(x)); +                    ControlToken::Continue +                } +                c => { +                    self.state = State::ScriptDataEscaped; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::ScriptDataDoubleEscaped => match self.read_char() { +                Some('-') => { +                    self.state = State::ScriptDataDoubleEscapedDash; +                    self.emitter.emit_string("-"); +                    ControlToken::Continue +                } +                Some('<') => { +                    self.state = State::ScriptDataDoubleEscapedLessThanSign; +                    self.emitter.emit_string("<"); +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.emit_string("\u{fffd}"); +                    ControlToken::Continue +                } +                None => { +                    self.emitter +                        .emit_error(Error::EofInScriptHtmlCommentLikeText); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.emitter.emit_string(ctostr!(x)); +                    ControlToken::Continue +                } +            }, +            State::ScriptDataDoubleEscapedDash => match self.read_char() { +                Some('-') => { +                    self.state = State::ScriptDataDoubleEscapedDashDash; +                    self.emitter.emit_string("-"); +                    ControlToken::Continue +                } +                Some('<') => { +                    self.state = State::ScriptDataDoubleEscapedLessThanSign; +                    self.emitter.emit_string("<"); +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.state = State::ScriptDataDoubleEscaped; +                    self.emitter.emit_string("\u{fffd}"); +                    ControlToken::Continue +                } +                None => { +                    self.emitter +                        .emit_error(Error::EofInScriptHtmlCommentLikeText); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.state = State::ScriptDataDoubleEscaped; +                    self.emitter.emit_string(ctostr!(x)); +                    ControlToken::Continue +                } +            }, +            State::ScriptDataDoubleEscapedDashDash => match self.read_char() { +                Some('-') => { +                    self.emitter.emit_string("-"); +                    ControlToken::Continue +                } +                Some('<') => { +                    self.emitter.emit_string("<"); +                    self.state = State::ScriptDataDoubleEscapedLessThanSign; +                    ControlToken::Continue +                } +                Some('>') => { +                    self.emitter.emit_string(">"); +                    self.state = State::ScriptData; +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.state = State::ScriptDataDoubleEscaped; +                    self.emitter.emit_string("\u{fffd}"); +                    ControlToken::Continue +                } +                None => { +                    self.emitter +                        .emit_error(Error::EofInScriptHtmlCommentLikeText); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.state = State::ScriptDataDoubleEscaped; +                    self.emitter.emit_string(ctostr!(x)); +                    ControlToken::Continue +                } +            }, +            State::ScriptDataDoubleEscapedLessThanSign => match self.read_char() { +                Some('/') => { +                    self.temporary_buffer.clear(); +                    self.state = State::ScriptDataDoubleEscapeEnd; +                    self.emitter.emit_string("/"); +                    ControlToken::Continue +                } +                c => { +                    self.state = State::ScriptDataDoubleEscaped; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::ScriptDataDoubleEscapeEnd => match self.read_char() { +                Some(x @ whitespace_pat!() | x @ '/' | x @ '>') => { +                    if self.temporary_buffer == "script" { +                        self.state = State::ScriptDataEscaped; +                    } else { +                        self.state = State::ScriptDataDoubleEscaped; +                    } + +                    self.emitter.emit_string(ctostr!(x)); +                    ControlToken::Continue +                } +                Some(x) if x.is_ascii_alphabetic() => { +                    self.temporary_buffer.push(x.to_ascii_lowercase()); +                    self.emitter.emit_string(ctostr!(x)); +                    ControlToken::Continue +                } +                c => { +                    self.state = State::ScriptDataDoubleEscaped; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::BeforeAttributeName => match self.read_char() { +                Some(whitespace_pat!()) => ControlToken::Continue, +                c @ Some('/' | '>') | c @ None => { +                    self.state = State::AfterAttributeName; +                    self.unread_char(c); +                    ControlToken::Continue +                } +                Some('=') => { +                    self.emitter +                        .emit_error(Error::UnexpectedEqualsSignBeforeAttributeName); +                    self.emitter.init_attribute(); +                    self.emitter.push_attribute_name("="); +                    self.state = State::AttributeName; +                    ControlToken::Continue +                } +                Some(x) => { +                    self.emitter.init_attribute(); +                    self.state = State::AttributeName; +                    self.unread_char(Some(x)); +                    ControlToken::Continue +                } +            }, +            State::AttributeName => match self.read_char() { +                c @ Some(whitespace_pat!() | '/' | '>') | c @ None => { +                    self.state = State::AfterAttributeName; +                    self.unread_char(c); +                    ControlToken::Continue +                } +                Some('=') => { +                    self.state = State::BeforeAttributeValue; +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.push_attribute_name("\u{fffd}"); +                    ControlToken::Continue +                } +                Some(x @ '"' | x @ '\'' | x @ '<') => { +                    self.emitter +                        .emit_error(Error::UnexpectedCharacterInAttributeName); +                    self.emitter +                        .push_attribute_name(ctostr!(x.to_ascii_lowercase())); +                    ControlToken::Continue +                } +                Some(x) => { +                    self.emitter +                        .push_attribute_name(ctostr!(x.to_ascii_lowercase())); +                    ControlToken::Continue +                } +            }, +            State::AfterAttributeName => match self.read_char() { +                Some(whitespace_pat!()) => ControlToken::Continue, +                Some('/') => { +                    self.state = State::SelfClosingStartTag; +                    ControlToken::Continue +                } +                Some('=') => { +                    self.state = State::BeforeAttributeValue; +                    ControlToken::Continue +                } +                Some('>') => { +                    self.state = State::Data; +                    self.emitter.emit_current_tag(); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInTag); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.emitter.init_attribute(); +                    self.state = State::AttributeName; +                    self.unread_char(Some(x)); +                    ControlToken::Continue +                } +            }, +            State::BeforeAttributeValue => match self.read_char() { +                Some(whitespace_pat!()) => ControlToken::Continue, +                Some('"') => { +                    self.state = State::AttributeValueDoubleQuoted; +                    ControlToken::Continue +                } +                Some('\'') => { +                    self.state = State::AttributeValueSingleQuoted; +                    ControlToken::Continue +                } +                Some('>') => { +                    self.emitter.emit_error(Error::MissingAttributeValue); +                    self.state = State::Data; +                    self.emitter.emit_current_tag(); +                    ControlToken::Continue +                } +                c => { +                    self.state = State::AttributeValueUnquoted; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::AttributeValueDoubleQuoted => match self.read_char() { +                Some('"') => { +                    self.state = State::AfterAttributeValueQuoted; +                    ControlToken::Continue +                } +                Some('&') => { +                    self.return_state = Some(State::AttributeValueDoubleQuoted); +                    self.state = State::CharacterReference; +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.push_attribute_value("\u{fffd}"); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInTag); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.emitter.push_attribute_value(ctostr!(x)); +                    ControlToken::Continue +                } +            }, +            State::AttributeValueSingleQuoted => match self.read_char() { +                Some('\'') => { +                    self.state = State::AfterAttributeValueQuoted; +                    ControlToken::Continue +                } +                Some('&') => { +                    self.return_state = Some(State::AttributeValueSingleQuoted); +                    self.state = State::CharacterReference; +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.push_attribute_value("\u{fffd}"); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInTag); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.emitter.push_attribute_value(ctostr!(x)); +                    ControlToken::Continue +                } +            }, +            State::AttributeValueUnquoted => match self.read_char() { +                Some(whitespace_pat!()) => { +                    self.state = State::BeforeAttributeName; +                    ControlToken::Continue +                } +                Some('&') => { +                    self.return_state = Some(State::AttributeValueUnquoted); +                    self.state = State::CharacterReference; +                    ControlToken::Continue +                } +                Some('>') => { +                    self.state = State::Data; +                    self.emitter.emit_current_tag(); +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.push_attribute_value("\u{fffd}"); +                    ControlToken::Continue +                } +                Some(x @ '"' | x @ '\'' | x @ '<' | x @ '=' | x @ '\u{60}') => { +                    self.emitter +                        .emit_error(Error::UnexpectedCharacterInUnquotedAttributeValue); +                    self.emitter.push_attribute_value(ctostr!(x)); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInTag); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.emitter.push_attribute_value(ctostr!(x)); +                    ControlToken::Continue +                } +            }, +            State::AfterAttributeValueQuoted => match self.read_char() { +                Some(whitespace_pat!()) => { +                    self.state = State::BeforeAttributeName; +                    ControlToken::Continue +                } +                Some('/') => { +                    self.state = State::SelfClosingStartTag; +                    ControlToken::Continue +                } +                Some('>') => { +                    self.state = State::Data; +                    self.emitter.emit_current_tag(); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInTag); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.emitter +                        .emit_error(Error::MissingWhitespaceBetweenAttributes); +                    self.state = State::BeforeAttributeName; +                    self.unread_char(Some(x)); +                    ControlToken::Continue +                } +            }, +            State::SelfClosingStartTag => match self.read_char() { +                Some('>') => { +                    self.emitter.set_self_closing(); +                    self.state = State::Data; +                    self.emitter.emit_current_tag(); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInTag); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.emitter.emit_error(Error::UnexpectedSolidusInTag); +                    self.state = State::BeforeAttributeName; +                    self.unread_char(Some(x)); +                    ControlToken::Continue +                } +            }, +            State::BogusComment => match self.read_char() { +                Some('>') => { +                    self.state = State::Data; +                    self.emitter.emit_current_comment(); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_current_comment(); +                    ControlToken::Eof +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.push_comment("\u{fffd}"); +                    ControlToken::Continue +                } +                Some(x) => { +                    self.emitter.push_comment(ctostr!(x)); +                    ControlToken::Continue +                } +            }, +            State::MarkupDeclarationOpen => match self.read_char() { +                Some('-') if self.try_read_string("-", true) => { +                    self.emitter.init_comment(); +                    self.state = State::CommentStart; +                    ControlToken::Continue +                } +                Some('d' | 'D') if self.try_read_string("octype", false) => { +                    self.state = State::Doctype; +                    ControlToken::Continue +                } +                Some('[') if self.try_read_string("CDATA[", true) => { +                    // missing: check for adjusted current element: we don't have an element stack +                    // at all +                    // +                    // missing: cdata transition +                    // +                    // let's hope that bogus comment can just sort of skip over cdata +                    self.emitter.emit_error(Error::CdataInHtmlContent); + +                    self.emitter.init_comment(); +                    self.emitter.push_comment("[CDATA["); +                    self.state = State::BogusComment; +                    ControlToken::Continue +                } +                c => { +                    self.emitter.emit_error(Error::IncorrectlyOpenedComment); +                    self.emitter.init_comment(); +                    self.state = State::BogusComment; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::CommentStart => match self.read_char() { +                Some('-') => { +                    self.state = State::CommentStartDash; +                    ControlToken::Continue +                } +                Some('>') => { +                    self.emitter.emit_error(Error::AbruptClosingOfEmptyComment); +                    self.state = State::Data; +                    self.emitter.emit_current_comment(); +                    ControlToken::Continue +                } +                c => { +                    self.unread_char(c); +                    self.state = State::Comment; +                    ControlToken::Continue +                } +            }, +            State::CommentStartDash => match self.read_char() { +                Some('-') => { +                    self.state = State::CommentEnd; +                    ControlToken::Continue +                } +                Some('>') => { +                    self.emitter.emit_error(Error::AbruptClosingOfEmptyComment); +                    self.state = State::Data; +                    self.emitter.emit_current_comment(); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInComment); +                    self.emitter.emit_current_comment(); +                    ControlToken::Eof +                } +                c @ Some(_) => { +                    self.emitter.push_comment("-"); +                    self.unread_char(c); +                    self.state = State::Comment; +                    ControlToken::Continue +                } +            }, +            State::Comment => match self.read_char() { +                Some('<') => { +                    self.emitter.push_comment("<"); +                    self.state = State::CommentLessThanSign; +                    ControlToken::Continue +                } +                Some('-') => { +                    self.state = State::CommentEndDash; +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.push_comment("\u{fffd}"); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInComment); +                    self.emitter.emit_current_comment(); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.emitter.push_comment(ctostr!(x)); +                    ControlToken::Continue +                } +            }, +            State::CommentLessThanSign => match self.read_char() { +                Some('!') => { +                    self.emitter.push_comment("!"); +                    self.state = State::CommentLessThanSignBang; +                    ControlToken::Continue +                } +                Some('<') => { +                    self.emitter.push_comment("<"); +                    ControlToken::Continue +                } +                c => { +                    self.unread_char(c); +                    self.state = State::Comment; +                    ControlToken::Continue +                } +            }, +            State::CommentLessThanSignBang => match self.read_char() { +                Some('-') => { +                    self.state = State::CommentLessThanSignBangDash; +                    ControlToken::Continue +                } +                c => { +                    self.unread_char(c); +                    self.state = State::Comment; +                    ControlToken::Continue +                } +            }, +            State::CommentLessThanSignBangDash => match self.read_char() { +                Some('-') => { +                    self.state = State::CommentLessThanSignBangDashDash; +                    ControlToken::Continue +                } +                c => { +                    self.unread_char(c); +                    self.state = State::CommentEndDash; +                    ControlToken::Continue +                } +            }, +            State::CommentLessThanSignBangDashDash => match self.read_char() { +                c @ Some('>') | c @ None => { +                    self.unread_char(c); +                    self.state = State::CommentEnd; +                    ControlToken::Continue +                } +                c => { +                    self.emitter.emit_error(Error::NestedComment); +                    self.unread_char(c); +                    self.state = State::CommentEnd; +                    ControlToken::Continue +                } +            }, +            State::CommentEndDash => match self.read_char() { +                Some('-') => { +                    self.state = State::CommentEnd; +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInComment); +                    self.emitter.emit_current_comment(); +                    ControlToken::Eof +                } +                c => { +                    self.emitter.push_comment("-"); +                    self.unread_char(c); +                    self.state = State::Comment; +                    ControlToken::Continue +                } +            }, +            State::CommentEnd => match self.read_char() { +                Some('>') => { +                    self.state = State::Data; +                    self.emitter.emit_current_comment(); +                    ControlToken::Continue +                } +                Some('!') => { +                    self.state = State::CommentEndBang; +                    ControlToken::Continue +                } +                Some('-') => { +                    self.emitter.push_comment("-"); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInComment); +                    self.emitter.emit_current_comment(); +                    ControlToken::Eof +                } +                c @ Some(_) => { +                    self.emitter.push_comment("-"); +                    self.emitter.push_comment("-"); +                    self.unread_char(c); +                    self.state = State::Comment; +                    ControlToken::Continue +                } +            }, +            State::CommentEndBang => match self.read_char() { +                Some('-') => { +                    self.emitter.push_comment("-"); +                    self.emitter.push_comment("-"); +                    self.emitter.push_comment("!"); +                    self.state = State::CommentEndDash; +                    ControlToken::Continue +                } +                Some('>') => { +                    self.emitter.emit_error(Error::IncorrectlyClosedComment); +                    self.state = State::Data; +                    self.emitter.emit_current_comment(); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInComment); +                    self.emitter.emit_current_comment(); +                    ControlToken::Eof +                } +                c @ Some(_) => { +                    self.emitter.push_comment("-"); +                    self.emitter.push_comment("-"); +                    self.emitter.push_comment("!"); +                    self.state = State::Comment; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::Doctype => match self.read_char() { +                Some(whitespace_pat!()) => { +                    self.state = State::BeforeDoctypeName; +                    ControlToken::Continue +                } +                c @ Some('>') => { +                    self.unread_char(c); +                    self.state = State::BeforeDoctypeName; +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInDoctype); +                    self.emitter.init_doctype(); +                    self.emitter.set_force_quirks(); +                    self.emitter.emit_current_doctype(); +                    ControlToken::Eof +                } +                c @ Some(_) => { +                    self.emitter +                        .emit_error(Error::MissingWhitespaceBeforeDoctypeName); +                    self.unread_char(c); +                    self.state = State::BeforeDoctypeName; +                    ControlToken::Continue +                } +            }, +            State::BeforeDoctypeName => match self.read_char() { +                Some(whitespace_pat!()) => ControlToken::Continue, +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.init_doctype(); +                    self.emitter.push_doctype_name("\u{fffd}"); +                    self.state = State::DoctypeName; +                    ControlToken::Continue +                } +                Some('>') => { +                    self.emitter.emit_error(Error::MissingDoctypeName); +                    self.emitter.init_doctype(); +                    self.emitter.set_force_quirks(); +                    self.state = State::Data; +                    self.emitter.emit_current_doctype(); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInDoctype); +                    self.emitter.init_doctype(); +                    self.emitter.set_force_quirks(); +                    self.emitter.emit_current_doctype(); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.emitter.init_doctype(); +                    self.emitter +                        .push_doctype_name(ctostr!(x.to_ascii_lowercase())); +                    self.state = State::DoctypeName; +                    ControlToken::Continue +                } +            }, +            State::DoctypeName => match self.read_char() { +                Some(whitespace_pat!()) => { +                    self.state = State::AfterDoctypeName; +                    ControlToken::Continue +                } +                Some('>') => { +                    self.state = State::Data; +                    self.emitter.emit_current_doctype(); +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.push_doctype_name("\u{fffd}"); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInDoctype); +                    self.emitter.set_force_quirks(); +                    self.emitter.emit_current_doctype(); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.emitter +                        .push_doctype_name(ctostr!(x.to_ascii_lowercase())); +                    ControlToken::Continue +                } +            }, +            State::AfterDoctypeName => match self.read_char() { +                Some(whitespace_pat!()) => ControlToken::Continue, +                Some('>') => { +                    self.state = State::Data; +                    self.emitter.emit_current_doctype(); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInDoctype); +                    self.emitter.set_force_quirks(); +                    self.emitter.emit_current_doctype(); +                    ControlToken::Eof +                } +                Some('p' | 'P') if self.try_read_string("ublic", false) => { +                    self.state = State::AfterDoctypePublicKeyword; +                    ControlToken::Continue +                } +                Some('s' | 'S') if self.try_read_string("ystem", false) => { +                    self.state = State::AfterDoctypeSystemKeyword; +                    ControlToken::Continue +                } +                c @ Some(_) => { +                    self.emitter +                        .emit_error(Error::InvalidCharacterSequenceAfterDoctypeName); +                    self.emitter.set_force_quirks(); +                    self.unread_char(c); +                    self.state = State::BogusDoctype; +                    ControlToken::Continue +                } +            }, +            State::AfterDoctypePublicKeyword => match self.read_char() { +                Some(whitespace_pat!()) => { +                    self.state = State::BeforeDoctypePublicIdentifier; +                    ControlToken::Continue +                } +                Some('"') => { +                    self.emitter +                        .emit_error(Error::MissingWhitespaceAfterDoctypePublicKeyword); +                    self.emitter.set_doctype_public_identifier(""); +                    self.state = State::DoctypePublicIdentifierDoubleQuoted; +                    ControlToken::Continue +                } +                Some('\'') => { +                    self.emitter +                        .emit_error(Error::MissingWhitespaceAfterDoctypePublicKeyword); +                    self.emitter.set_doctype_public_identifier(""); +                    self.state = State::DoctypePublicIdentifierSingleQuoted; +                    ControlToken::Continue +                } +                Some('>') => { +                    self.emitter +                        .emit_error(Error::MissingDoctypePublicIdentifier); +                    self.emitter.set_force_quirks(); +                    self.state = State::Data; +                    self.emitter.emit_current_doctype(); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInDoctype); +                    self.emitter.set_force_quirks(); +                    self.emitter.emit_current_doctype(); +                    ControlToken::Eof +                } +                c @ Some(_) => { +                    self.emitter +                        .emit_error(Error::MissingQuoteBeforeDoctypePublicIdentifier); +                    self.emitter.set_force_quirks(); +                    self.unread_char(c); +                    self.state = State::BogusDoctype; +                    ControlToken::Continue +                } +            }, +            State::BeforeDoctypePublicIdentifier => match self.read_char() { +                Some(whitespace_pat!()) => ControlToken::Continue, +                Some('"') => { +                    self.emitter.set_doctype_public_identifier(""); +                    self.state = State::DoctypePublicIdentifierDoubleQuoted; +                    ControlToken::Continue +                } +                Some('\'') => { +                    self.emitter.set_doctype_public_identifier(""); +                    self.state = State::DoctypePublicIdentifierSingleQuoted; +                    ControlToken::Continue +                } +                Some('>') => { +                    self.emitter +                        .emit_error(Error::MissingDoctypePublicIdentifier); +                    self.emitter.set_force_quirks(); +                    self.state = State::Data; +                    self.emitter.emit_current_doctype(); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInDoctype); +                    self.emitter.set_force_quirks(); +                    self.emitter.emit_current_doctype(); +                    ControlToken::Eof +                } +                c @ Some(_) => { +                    self.emitter +                        .emit_error(Error::MissingQuoteBeforeDoctypePublicIdentifier); +                    self.emitter.set_force_quirks(); +                    self.unread_char(c); +                    self.state = State::BogusDoctype; +                    ControlToken::Continue +                } +            }, +            State::DoctypePublicIdentifierDoubleQuoted => match self.read_char() { +                Some('"') => { +                    self.state = State::AfterDoctypePublicIdentifier; +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.push_doctype_public_identifier("\u{fffd}"); +                    ControlToken::Continue +                } +                Some('>') => { +                    self.emitter +                        .emit_error(Error::AbruptDoctypePublicIdentifier); +                    self.emitter.set_force_quirks(); +                    self.state = State::Data; +                    self.emitter.emit_current_doctype(); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInDoctype); +                    self.emitter.set_force_quirks(); +                    self.emitter.emit_current_doctype(); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.emitter.push_doctype_public_identifier(ctostr!(x)); +                    ControlToken::Continue +                } +            }, +            State::DoctypePublicIdentifierSingleQuoted => match self.read_char() { +                Some('\'') => { +                    self.state = State::AfterDoctypePublicIdentifier; +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.push_doctype_public_identifier("\u{fffd}"); +                    ControlToken::Continue +                } +                Some('>') => { +                    self.emitter +                        .emit_error(Error::AbruptDoctypePublicIdentifier); +                    self.emitter.set_force_quirks(); +                    self.state = State::Data; +                    self.emitter.emit_current_doctype(); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInDoctype); +                    self.emitter.set_force_quirks(); +                    self.emitter.emit_current_doctype(); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.emitter.push_doctype_public_identifier(ctostr!(x)); +                    ControlToken::Continue +                } +            }, +            State::AfterDoctypePublicIdentifier => match self.read_char() { +                Some(whitespace_pat!()) => { +                    self.state = State::BetweenDoctypePublicAndSystemIdentifiers; +                    ControlToken::Continue +                } +                Some('>') => { +                    self.state = State::Data; +                    self.emitter.emit_current_doctype(); +                    ControlToken::Continue +                } +                Some('"') => { +                    self.emitter.emit_error( +                        Error::MissingWhitespaceBetweenDoctypePublicAndSystemIdentifiers, +                    ); +                    self.emitter.set_doctype_system_identifier(""); +                    self.state = State::DoctypeSystemIdentifierDoubleQuoted; +                    ControlToken::Continue +                } +                Some('\'') => { +                    self.emitter.emit_error( +                        Error::MissingWhitespaceBetweenDoctypePublicAndSystemIdentifiers, +                    ); +                    self.emitter.set_doctype_system_identifier(""); +                    self.state = State::DoctypeSystemIdentifierSingleQuoted; +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInDoctype); +                    self.emitter.set_force_quirks(); +                    self.emitter.emit_current_doctype(); +                    ControlToken::Eof +                } +                c @ Some(_) => { +                    self.emitter +                        .emit_error(Error::MissingQuoteBeforeDoctypeSystemIdentifier); +                    self.emitter.set_force_quirks(); +                    self.unread_char(c); +                    self.state = State::BogusDoctype; +                    ControlToken::Continue +                } +            }, +            State::BetweenDoctypePublicAndSystemIdentifiers => match self.read_char() { +                Some(whitespace_pat!()) => ControlToken::Continue, +                Some('>') => { +                    self.state = State::Data; +                    self.emitter.emit_current_doctype(); +                    ControlToken::Continue +                } +                Some('"') => { +                    self.emitter.set_doctype_system_identifier(""); +                    self.state = State::DoctypeSystemIdentifierDoubleQuoted; +                    ControlToken::Continue +                } +                Some('\'') => { +                    self.emitter.set_doctype_system_identifier(""); +                    self.state = State::DoctypeSystemIdentifierSingleQuoted; +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInDoctype); +                    self.emitter.set_force_quirks(); +                    self.emitter.emit_current_doctype(); +                    ControlToken::Eof +                } +                c @ Some(_) => { +                    self.emitter +                        .emit_error(Error::MissingQuoteBeforeDoctypeSystemIdentifier); +                    self.emitter.set_force_quirks(); +                    self.state = State::BogusDoctype; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::AfterDoctypeSystemKeyword => match self.read_char() { +                Some(whitespace_pat!()) => { +                    self.state = State::BeforeDoctypeSystemIdentifier; +                    ControlToken::Continue +                } +                Some('"') => { +                    self.emitter +                        .emit_error(Error::MissingWhitespaceAfterDoctypeSystemKeyword); +                    self.emitter.set_doctype_system_identifier(""); +                    self.state = State::DoctypeSystemIdentifierDoubleQuoted; +                    ControlToken::Continue +                } +                Some('\'') => { +                    self.emitter +                        .emit_error(Error::MissingWhitespaceAfterDoctypeSystemKeyword); +                    self.emitter.set_doctype_system_identifier(""); +                    self.state = State::DoctypeSystemIdentifierSingleQuoted; +                    ControlToken::Continue +                } +                Some('>') => { +                    self.emitter +                        .emit_error(Error::MissingDoctypeSystemIdentifier); +                    self.emitter.set_force_quirks(); +                    self.state = State::Data; +                    self.emitter.emit_current_doctype(); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInDoctype); +                    self.emitter.set_force_quirks(); +                    self.emitter.emit_current_doctype(); +                    ControlToken::Eof +                } +                c @ Some(_) => { +                    self.emitter +                        .emit_error(Error::MissingQuoteBeforeDoctypeSystemIdentifier); +                    self.emitter.set_force_quirks(); +                    self.state = State::BogusDoctype; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::BeforeDoctypeSystemIdentifier => match self.read_char() { +                Some(whitespace_pat!()) => ControlToken::Continue, +                Some('"') => { +                    self.emitter.set_doctype_system_identifier(""); +                    self.state = State::DoctypeSystemIdentifierDoubleQuoted; +                    ControlToken::Continue +                } +                Some('\'') => { +                    self.emitter.set_doctype_system_identifier(""); +                    self.state = State::DoctypeSystemIdentifierSingleQuoted; +                    ControlToken::Continue +                } +                Some('>') => { +                    self.emitter +                        .emit_error(Error::MissingDoctypeSystemIdentifier); +                    self.emitter.set_force_quirks(); +                    self.state = State::Data; +                    self.emitter.emit_current_doctype(); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInDoctype); +                    self.emitter.set_force_quirks(); +                    self.emitter.emit_current_doctype(); +                    ControlToken::Eof +                } +                c @ Some(_) => { +                    self.emitter +                        .emit_error(Error::MissingQuoteBeforeDoctypeSystemIdentifier); +                    self.emitter.set_force_quirks(); +                    self.state = State::BogusDoctype; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::DoctypeSystemIdentifierDoubleQuoted => match self.read_char() { +                Some('"') => { +                    self.state = State::AfterDoctypeSystemIdentifier; +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.push_doctype_system_identifier("\u{fffd}"); +                    ControlToken::Continue +                } +                Some('>') => { +                    self.emitter +                        .emit_error(Error::AbruptDoctypeSystemIdentifier); +                    self.emitter.set_force_quirks(); +                    self.state = State::Data; +                    self.emitter.emit_current_doctype(); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInDoctype); +                    self.emitter.set_force_quirks(); +                    self.emitter.emit_current_doctype(); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.emitter.push_doctype_system_identifier(ctostr!(x)); +                    ControlToken::Continue +                } +            }, +            State::DoctypeSystemIdentifierSingleQuoted => match self.read_char() { +                Some('\'') => { +                    self.state = State::AfterDoctypeSystemIdentifier; +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    self.emitter.push_doctype_system_identifier("\u{fffd}"); +                    ControlToken::Continue +                } +                Some('>') => { +                    self.emitter +                        .emit_error(Error::AbruptDoctypeSystemIdentifier); +                    self.emitter.set_force_quirks(); +                    self.state = State::Data; +                    self.emitter.emit_current_doctype(); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInDoctype); +                    self.emitter.set_force_quirks(); +                    self.emitter.emit_current_doctype(); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.emitter.push_doctype_system_identifier(ctostr!(x)); +                    ControlToken::Continue +                } +            }, +            State::AfterDoctypeSystemIdentifier => match self.read_char() { +                Some(whitespace_pat!()) => ControlToken::Continue, +                Some('>') => { +                    self.state = State::Data; +                    self.emitter.emit_current_doctype(); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInDoctype); +                    self.emitter.set_force_quirks(); +                    self.emitter.emit_current_doctype(); +                    ControlToken::Eof +                } +                c @ Some(_) => { +                    self.emitter +                        .emit_error(Error::UnexpectedCharacterAfterDoctypeSystemIdentifier); +                    self.unread_char(c); +                    self.state = State::BogusDoctype; +                    ControlToken::Continue +                } +            }, +            State::BogusDoctype => match self.read_char() { +                Some('>') => { +                    self.state = State::Data; +                    self.emitter.emit_current_doctype(); +                    ControlToken::Continue +                } +                Some('\0') => { +                    self.emitter.emit_error(Error::UnexpectedNullCharacter); +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_current_doctype(); +                    ControlToken::Eof +                } +                Some(_) => ControlToken::Continue, +            }, +            State::CdataSection => match self.read_char() { +                Some(']') => { +                    self.state = State::CdataSectionBracket; +                    ControlToken::Continue +                } +                None => { +                    self.emitter.emit_error(Error::EofInCdata); +                    ControlToken::Eof +                } +                Some(x) => { +                    self.emitter.emit_string(ctostr!(x)); +                    ControlToken::Continue +                } +            }, +            State::CdataSectionBracket => match self.read_char() { +                Some(']') => { +                    self.state = State::CdataSectionEnd; +                    ControlToken::Continue +                } +                c => { +                    self.emitter.emit_string("]"); +                    self.state = State::CdataSection; +                    self.unread_char(c); +                    ControlToken::Continue +                } +            }, +            State::CdataSectionEnd => match self.read_char() { +                Some(']') => { +                    self.emitter.emit_string("]"); +                    ControlToken::Continue +                } +                Some('>') => { +                    self.state = State::Data; +                    ControlToken::Continue +                } +                c => { +                    self.emitter.emit_string("]]"); +                    self.unread_char(c); +                    self.state = State::CdataSection; +                    ControlToken::Continue +                } +            }, +            State::CharacterReference => { +                self.temporary_buffer.clear(); +                self.temporary_buffer.push('&'); +                match self.read_char() { +                    Some(x) if x.is_ascii_alphanumeric() => { +                        self.unread_char(Some(x)); +                        self.state = State::NamedCharacterReference; +                        ControlToken::Continue +                    } +                    Some('#') => { +                        self.temporary_buffer.push('#'); +                        self.state = State::NumericCharacterReference; +                        ControlToken::Continue +                    } +                    c => { +                        self.flush_code_points_consumed_as_character_reference(); +                        self.state = self.return_state.take().unwrap(); +                        self.unread_char(c); +                        ControlToken::Continue +                    } +                } +            } +            State::NamedCharacterReference => { +                let c = self.read_char(); + +                let char_ref = c.and_then(|x| { +                    Some(( +                        x, +                        entities::try_read_character_reference(x, |x| { +                            self.try_read_string(x, true) +                        })?, +                    )) +                }); + +                if let Some((x, char_ref)) = char_ref { +                    self.temporary_buffer.push(x); +                    self.temporary_buffer.push_str(char_ref.name); +                    let char_ref_name_last_character = char_ref.name.chars().last(); +                    let next_character = self.next_input_character(); +                    if self.is_consumed_as_part_of_an_attribute() +                        && char_ref_name_last_character != Some(';') +                        && matches!(next_character, Some(x) if x == '=' || x.is_ascii_alphanumeric()) +                    { +                        self.flush_code_points_consumed_as_character_reference(); +                        self.state = self.return_state.take().unwrap(); +                        ControlToken::Continue +                    } else { +                        if char_ref_name_last_character != Some(';') { +                            self.emitter +                                .emit_error(Error::MissingSemicolonAfterCharacterReference); +                        } + +                        self.temporary_buffer.clear(); +                        self.temporary_buffer.push_str(char_ref.characters); +                        self.flush_code_points_consumed_as_character_reference(); +                        self.state = self.return_state.take().unwrap(); +                        ControlToken::Continue +                    } +                } else { +                    self.unread_char(c); +                    self.flush_code_points_consumed_as_character_reference(); +                    self.state = State::AmbiguousAmpersand; +                    ControlToken::Continue +                } +            } +            State::AmbiguousAmpersand => match self.read_char() { +                Some(x) if x.is_ascii_alphanumeric() => { +                    if self.is_consumed_as_part_of_an_attribute() { +                        self.emitter.push_attribute_value(ctostr!(x)); +                    } else { +                        self.emitter.emit_string(ctostr!(x)); +                    } + +                    ControlToken::Continue +                } +                c @ Some(';') => { +                    self.emitter +                        .emit_error(Error::UnknownNamedCharacterReference); +                    self.unread_char(c); +                    self.state = self.return_state.take().unwrap(); +                    ControlToken::Continue +                } +                c => { +                    self.unread_char(c); +                    self.state = self.return_state.take().unwrap(); +                    ControlToken::Continue +                } +            }, +            State::NumericCharacterReference => { +                self.character_reference_code = 0; +                match self.read_char() { +                    Some(x @ 'x' | x @ 'X') => { +                        self.temporary_buffer.push(x); +                        self.state = State::HexadecimalCharacterReferenceStart; +                        ControlToken::Continue +                    } +                    c => { +                        self.unread_char(c); +                        self.state = State::DecimalCharacterReferenceStart; +                        ControlToken::Continue +                    } +                } +            } +            State::HexadecimalCharacterReferenceStart => match self.read_char() { +                c @ Some('0'..='9' | 'A'..='F' | 'a'..='f') => { +                    self.unread_char(c); +                    self.state = State::HexadecimalCharacterReference; +                    ControlToken::Continue +                } +                c => { +                    self.emitter +                        .emit_error(Error::AbsenceOfDigitsInNumericCharacterReference); +                    self.flush_code_points_consumed_as_character_reference(); +                    self.unread_char(c); +                    self.state = self.return_state.take().unwrap(); +                    ControlToken::Continue +                } +            }, +            State::DecimalCharacterReferenceStart => match self.read_char() { +                Some(x @ ascii_digit_pat!()) => { +                    self.unread_char(Some(x)); +                    self.state = State::DecimalCharacterReference; +                    ControlToken::Continue +                } +                c => { +                    self.emitter +                        .emit_error(Error::AbsenceOfDigitsInNumericCharacterReference); +                    self.flush_code_points_consumed_as_character_reference(); +                    self.unread_char(c); +                    self.state = self.return_state.take().unwrap(); +                    ControlToken::Continue +                } +            }, +            State::HexadecimalCharacterReference => match self.read_char() { +                Some(x @ ascii_digit_pat!()) => { +                    mutate_character_reference!(*16 + x - 0x0030); +                    ControlToken::Continue +                } +                Some(x @ 'A'..='F') => { +                    mutate_character_reference!(*16 + x - 0x0037); +                    ControlToken::Continue +                } +                Some(x @ 'a'..='f') => { +                    mutate_character_reference!(*16 + x - 0x0057); +                    ControlToken::Continue +                } +                Some(';') => { +                    self.state = State::NumericCharacterReferenceEnd; +                    ControlToken::Continue +                } +                c => { +                    self.emitter +                        .emit_error(Error::MissingSemicolonAfterCharacterReference); +                    self.unread_char(c); +                    self.state = State::NumericCharacterReferenceEnd; +                    ControlToken::Continue +                } +            }, +            State::DecimalCharacterReference => match self.read_char() { +                Some(x @ ascii_digit_pat!()) => { +                    mutate_character_reference!(*10 + x - 0x0030); +                    ControlToken::Continue +                } +                Some(';') => { +                    self.state = State::NumericCharacterReferenceEnd; +                    ControlToken::Continue +                } +                c => { +                    self.emitter +                        .emit_error(Error::MissingSemicolonAfterCharacterReference); +                    self.unread_char(c); +                    self.state = State::NumericCharacterReferenceEnd; +                    ControlToken::Continue +                } +            }, +            State::NumericCharacterReferenceEnd => { +                match self.character_reference_code { +                    0x00 => { +                        self.emitter.emit_error(Error::NullCharacterReference); +                        self.character_reference_code = 0xfffd; +                    } +                    0x110000.. => { +                        self.emitter +                            .emit_error(Error::CharacterReferenceOutsideUnicodeRange); +                        self.character_reference_code = 0xfffd; +                    } +                    surrogate_pat!() => { +                        self.emitter.emit_error(Error::SurrogateCharacterReference); +                        self.character_reference_code = 0xfffd; +                    } +                    // noncharacter +                    noncharacter_pat!() => { +                        self.emitter +                            .emit_error(Error::NoncharacterCharacterReference); +                    } +                    // 0x000d, or a control that is not whitespace +                    x @ 0x000d | x @ control_pat!() +                        if !matches!(x, 0x0009 | 0x000a | 0x000c | 0x0020) => +                    { +                        self.emitter.emit_error(Error::ControlCharacterReference); +                        self.character_reference_code = match x { +                            0x80 => 0x20AC, // EURO SIGN (€) +                            0x82 => 0x201A, // SINGLE LOW-9 QUOTATION MARK (‚) +                            0x83 => 0x0192, // LATIN SMALL LETTER F WITH HOOK (ƒ) +                            0x84 => 0x201E, // DOUBLE LOW-9 QUOTATION MARK („) +                            0x85 => 0x2026, // HORIZONTAL ELLIPSIS (…) +                            0x86 => 0x2020, // DAGGER (†) +                            0x87 => 0x2021, // DOUBLE DAGGER (‡) +                            0x88 => 0x02C6, // MODIFIER LETTER CIRCUMFLEX ACCENT (ˆ) +                            0x89 => 0x2030, // PER MILLE SIGN (‰) +                            0x8A => 0x0160, // LATIN CAPITAL LETTER S WITH CARON (Š) +                            0x8B => 0x2039, // SINGLE LEFT-POINTING ANGLE QUOTATION MARK (‹) +                            0x8C => 0x0152, // LATIN CAPITAL LIGATURE OE (Œ) +                            0x8E => 0x017D, // LATIN CAPITAL LETTER Z WITH CARON (Ž) +                            0x91 => 0x2018, // LEFT SINGLE QUOTATION MARK (‘) +                            0x92 => 0x2019, // RIGHT SINGLE QUOTATION MARK (’) +                            0x93 => 0x201C, // LEFT DOUBLE QUOTATION MARK (“) +                            0x94 => 0x201D, // RIGHT DOUBLE QUOTATION MARK (”) +                            0x95 => 0x2022, // BULLET (•) +                            0x96 => 0x2013, // EN DASH (–) +                            0x97 => 0x2014, // EM DASH (—) +                            0x98 => 0x02DC, // SMALL TILDE (˜) +                            0x99 => 0x2122, // TRADE MARK SIGN (™) +                            0x9A => 0x0161, // LATIN SMALL LETTER S WITH CARON (š) +                            0x9B => 0x203A, // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (›) +                            0x9C => 0x0153, // LATIN SMALL LIGATURE OE (œ) +                            0x9E => 0x017E, // LATIN SMALL LETTER Z WITH CARON (ž) +                            0x9F => 0x0178, // LATIN CAPITAL LETTER Y WITH DIAERESIS (Ÿ) +                            _ => self.character_reference_code, +                        }; +                    } +                    _ => (), +                } + +                self.temporary_buffer.clear(); +                self.temporary_buffer +                    .push(std::char::from_u32(self.character_reference_code).unwrap()); +                self.flush_code_points_consumed_as_character_reference(); +                self.state = self.return_state.take().unwrap(); +                ControlToken::Continue +            } +        } +    } +} + +impl<R: Reader, E: Emitter> Iterator for Tokenizer<R, E> { +    type Item = E::Token; + +    fn next(&mut self) -> Option<Self::Item> { +        loop { +            if let Some(token) = self.emitter.pop_token() { +                break Some(token); +            } else if !self.eof { +                match self.consume() { +                    ControlToken::Continue => (), +                    ControlToken::Eof => { +                        self.eof = true; +                        self.emitter.emit_eof(); +                    } +                } +            } else { +                break None; +            } +        } +    } +} diff --git a/src/machine.rs b/src/machine.rs new file mode 100644 index 0000000..67db1b9 --- /dev/null +++ b/src/machine.rs @@ -0,0 +1,164 @@ +macro_rules! surrogate_pat { +    () => { +        0xd800..=0xdfff +    }; +} + +pub(crate) use surrogate_pat; + +macro_rules! control_pat { +    () => (0x0d | 0x0000..=0x001f | 0x007f..=0x009f) +} + +pub(crate) use control_pat; + +macro_rules! ascii_digit_pat { +    () => { +        '0'..='9' +    }; +} + +pub(crate) use ascii_digit_pat; + +macro_rules! whitespace_pat { +    () => { +        '\t' | '\u{0A}' | '\u{0C}' | ' ' +    }; +} + +pub(crate) use whitespace_pat; + +macro_rules! noncharacter_pat { +    () => { +        0xfdd0 +            ..=0xfdef +                | 0xfffe +                | 0xffff +                | 0x1fffe +                | 0x1ffff +                | 0x2fffe +                | 0x2ffff +                | 0x3fffe +                | 0x3ffff +                | 0x4fffe +                | 0x4ffff +                | 0x5fffe +                | 0x5ffff +                | 0x6fffe +                | 0x6ffff +                | 0x7fffe +                | 0x7ffff +                | 0x8fffe +                | 0x8ffff +                | 0x9fffe +                | 0x9ffff +                | 0xafffe +                | 0xaffff +                | 0xbfffe +                | 0xbffff +                | 0xcfffe +                | 0xcffff +                | 0xdfffe +                | 0xdffff +                | 0xefffe +                | 0xeffff +                | 0xffffe +                | 0xfffff +                | 0x10fffe +                | 0x10ffff +    }; +} + +pub(crate) use noncharacter_pat; + +// When integration tests are running, this enum is public and we get warnings about missing docs. +// However, it's not actually part of public API. +#[allow(missing_docs)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum State { +    Data, +    RcData, +    RawText, +    ScriptData, +    PlainText, +    TagOpen, +    EndTagOpen, +    TagName, +    RcDataLessThanSign, +    RcDataEndTagOpen, +    RcDataEndTagName, +    RawTextLessThanSign, +    RawTextEndTagOpen, +    RawTextEndTagName, +    ScriptDataLessThanSign, +    ScriptDataEndTagOpen, +    ScriptDataEndTagName, +    ScriptDataEscapeStart, +    ScriptDataEscapeStartDash, +    ScriptDataEscaped, +    ScriptDataEscapedDash, +    ScriptDataEscapedDashDash, +    ScriptDataEscapedLessThanSign, +    ScriptDataEscapedEndTagOpen, +    ScriptDataEscapedEndTagName, +    ScriptDataDoubleEscapeStart, +    ScriptDataDoubleEscaped, +    ScriptDataDoubleEscapedDash, +    ScriptDataDoubleEscapedDashDash, +    ScriptDataDoubleEscapedLessThanSign, +    ScriptDataDoubleEscapeEnd, +    BeforeAttributeName, +    AttributeName, +    AfterAttributeName, +    BeforeAttributeValue, +    AttributeValueDoubleQuoted, +    AttributeValueSingleQuoted, +    AttributeValueUnquoted, +    AfterAttributeValueQuoted, +    SelfClosingStartTag, +    BogusComment, +    MarkupDeclarationOpen, +    CommentStart, +    CommentStartDash, +    Comment, +    CommentLessThanSign, +    CommentLessThanSignBang, +    CommentLessThanSignBangDash, +    CommentLessThanSignBangDashDash, +    CommentEndDash, +    CommentEnd, +    CommentEndBang, +    Doctype, +    BeforeDoctypeName, +    DoctypeName, +    AfterDoctypeName, +    AfterDoctypePublicKeyword, +    BeforeDoctypePublicIdentifier, +    DoctypePublicIdentifierDoubleQuoted, +    DoctypePublicIdentifierSingleQuoted, +    AfterDoctypePublicIdentifier, +    BetweenDoctypePublicAndSystemIdentifiers, +    AfterDoctypeSystemKeyword, +    BeforeDoctypeSystemIdentifier, +    DoctypeSystemIdentifierDoubleQuoted, +    DoctypeSystemIdentifierSingleQuoted, +    AfterDoctypeSystemIdentifier, +    BogusDoctype, +    CdataSection, +    CdataSectionBracket, +    CdataSectionEnd, +    CharacterReference, +    NamedCharacterReference, +    AmbiguousAmpersand, +    NumericCharacterReference, +    HexadecimalCharacterReferenceStart, +    DecimalCharacterReferenceStart, +    HexadecimalCharacterReference, +    DecimalCharacterReference, +    NumericCharacterReferenceEnd, +} + +pub enum ControlToken { +    Eof, +    Continue, +} diff --git a/src/reader.rs b/src/reader.rs new file mode 100644 index 0000000..d2cae92 --- /dev/null +++ b/src/reader.rs @@ -0,0 +1,114 @@ +/// An object that provides characters to the tokenizer. +/// +/// See [`crate::Tokenizer::new`] for more information. +pub trait Reader { +    /// Return a new character from the input stream. +    /// +    /// Newlines have to be normalized as described in [Preprocessing the input +    /// stream](https://html.spec.whatwg.org/#preprocessing-the-input-stream), however error +    /// emission is done within the tokenizer. +    fn read_char(&mut self) -> Option<char>; + +    /// Attempt to read an entire string at once, either case-insensitively or not. +    /// +    /// `case_sensitive=false` means that characters of the input stream should be compared while +    /// ignoring ASCII-casing. +    /// +    /// It can be assumed that this function is never called with a string that contains `\r` or +    /// `\n`. +    /// +    /// If the next characters equal to `s`, this function consumes the respective characters from +    /// the input stream and returns `true`. If not, it does nothing and returns `false`. +    fn try_read_string(&mut self, s: &str, case_sensitive: bool) -> bool; +} + +/// An object that can be converted into a [`crate::Reader`]. +/// +/// For example, any utf8-string can be converted into a `StringReader`, such that +/// `Tokenizer::new("mystring")` and `Tokenizer::new(&String::new("foo"))` work. +pub trait Readable<'a> { +    /// The reader type to which this type should be converted. +    type Reader: Reader + 'a; + +    /// Convert self to some sort of reader. +    fn to_reader(self) -> Self::Reader; +} + +impl<'a, R: 'a + Reader> Readable<'a> for R { +    type Reader = Self; + +    fn to_reader(self) -> Self::Reader { +        self +    } +} + +/// A helper struct to seek forwards and backwards in strings. Used by the tokenizer to read HTML +/// from strings. +pub struct StringReader<'a> { +    input: &'a str, +    pos: usize, +} + +impl<'a> StringReader<'a> { +    fn new(input: &'a str) -> Self { +        StringReader { input, pos: 0 } +    } + +    fn peek_char(&self) -> Option<char> { +        self.input.get(self.pos..)?.chars().next() +    } +} + +impl<'a> Reader for StringReader<'a> { +    fn read_char(&mut self) -> Option<char> { +        let mut r1 = match self.peek_char() { +            Some(x) => x, +            None => { +                self.pos += 1; +                return None; +            } +        }; + +        self.pos += r1.len_utf8(); + +        if r1 == '\r' { +            r1 = '\n'; +            let r2 = self.peek_char(); +            if r2 == Some('\n') { +                self.pos += r2.map(char::len_utf8).unwrap_or(0); +            } +        } + +        Some(r1) +    } + +    fn try_read_string(&mut self, s1: &str, case_sensitive: bool) -> bool { +        // we do not need to call validate_char here because `s` hopefully does not contain invalid +        // characters + +        if let Some(s2) = self.input.get(self.pos..self.pos + s1.len()) { +            if s1 == s2 || (!case_sensitive && s1.eq_ignore_ascii_case(s2)) { +                self.pos += s1.len(); +                return true; +            } +        } + +        false +    } +} + +impl<'a> Readable<'a> for &'a str { +    type Reader = StringReader<'a>; + +    fn to_reader(self) -> Self::Reader { +        StringReader::new(self) +    } +} + +impl<'a> Readable<'a> for &'a String { +    type Reader = StringReader<'a>; + +    fn to_reader(self) -> Self::Reader { +        StringReader::new(self.as_str()) +    } +}  | 
