lol_html 1.2.1

Streaming HTML rewriter/parser with CSS selector-based API
Documentation
mod text_decoder;
mod to_token;

use self::text_decoder::TextDecoder;
use super::*;
use crate::base::SharedEncoding;
use crate::parser::Lexeme;
use crate::rewriter::RewritingError;
use bitflags::bitflags;

pub use self::to_token::{ToToken, ToTokenResult};

bitflags! {
    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
    pub struct TokenCaptureFlags: u8 {
        const TEXT = 0b0000_0001;
        const COMMENTS = 0b0000_0010;
        const NEXT_START_TAG = 0b0000_0100;
        const NEXT_END_TAG = 0b0000_1000;
        const DOCTYPES = 0b0001_0000;
    }
}

#[derive(Debug)]
pub enum TokenCapturerEvent<'i> {
    LexemeConsumed,
    TokenProduced(Box<Token<'i>>),
}

type CapturerEventHandler<'h> = &'h mut dyn FnMut(TokenCapturerEvent) -> Result<(), RewritingError>;

pub struct TokenCapturer {
    encoding: SharedEncoding,
    text_decoder: TextDecoder,
    capture_flags: TokenCaptureFlags,
}

impl TokenCapturer {
    pub fn new(capture_flags: TokenCaptureFlags, encoding: SharedEncoding) -> Self {
        TokenCapturer {
            encoding: SharedEncoding::clone(&encoding),
            text_decoder: TextDecoder::new(encoding),
            capture_flags,
        }
    }

    #[inline]
    pub fn has_captures(&self) -> bool {
        !self.capture_flags.is_empty()
    }

    #[inline]
    pub fn set_capture_flags(&mut self, flags: TokenCaptureFlags) {
        self.capture_flags = flags;
    }

    #[inline]
    pub fn flush_pending_text(
        &mut self,
        event_handler: CapturerEventHandler,
    ) -> Result<(), RewritingError> {
        self.text_decoder.flush_pending(event_handler)
    }

    pub fn feed<'i, T>(
        &mut self,
        lexeme: &Lexeme<'i, T>,
        mut event_handler: impl FnMut(TokenCapturerEvent) -> Result<(), RewritingError>,
    ) -> Result<(), RewritingError>
    where
        Lexeme<'i, T>: ToToken,
    {
        match lexeme.to_token(&mut self.capture_flags, self.encoding.get()) {
            ToTokenResult::Token(token) => {
                self.flush_pending_text(&mut event_handler)?;
                event_handler(TokenCapturerEvent::LexemeConsumed)?;
                event_handler(TokenCapturerEvent::TokenProduced(token))
            }
            ToTokenResult::Text(text_type) => {
                if self.capture_flags.contains(TokenCaptureFlags::TEXT) {
                    event_handler(TokenCapturerEvent::LexemeConsumed)?;

                    self.text_decoder
                        .feed_text(&lexeme.raw(), text_type, &mut event_handler)?;
                }

                Ok(())
            }
            ToTokenResult::None => self.flush_pending_text(&mut event_handler),
        }
    }
}