tl/lib.rs
1#![cfg_attr(feature = "simd", feature(portable_simd))]
2#![doc = include_str!("../README.md")]
3#![deny(missing_docs)]
4
5mod bytes;
6/// Errors that occur throughout the crate
7pub mod errors;
8/// Inline data structures
9pub mod inline;
10mod parser;
11/// Query selector API
12pub mod queryselector;
13mod stream;
14#[cfg(test)]
15mod tests;
16mod util;
17mod vdom;
18
19#[doc(hidden)]
20#[cfg(feature = "__INTERNALS_DO_NOT_USE")]
21pub mod simd;
22#[cfg(not(feature = "__INTERNALS_DO_NOT_USE"))]
23mod simd;
24
25pub use bytes::Bytes;
26pub use errors::ParseError;
27pub use parser::*;
28use queryselector::Selector;
29pub use vdom::{VDom, VDomGuard};
30
31/// Parses the given input string
32///
33/// This is the "entry point" and function that is called to parse HTML.
34/// The input string must be kept alive, and must outlive `VDom`.
35/// If you need an "owned" version that takes an input string and can be kept around forever,
36/// consider using `parse_owned()`.
37///
38/// # Errors
39/// Throughout the parser it is assumed that spans never overflow a `u32`.
40/// To prevent this, this function will return an error if the input string length would overflow a `u32`.
41/// If the input string length fits in a `u32`, then it is safe to assume that none of the substrings can overflow a `u32`.
42///
43/// # Example
44/// ```
45/// # use tl::*;
46/// let dom = parse("<div>Hello, world!</div>", ParserOptions::default()).unwrap();
47/// assert_eq!(dom.query_selector("div").unwrap().count(), 1);
48/// ```
49pub fn parse(input: &str, options: ParserOptions) -> Result<VDom<'_>, ParseError> {
50 let mut parser = Parser::new(input, options);
51 parser.parse()?;
52 Ok(VDom::from(parser))
53}
54
55/// Parses a query selector
56///
57/// # Example
58/// ```
59/// # use tl::queryselector::selector::Selector;
60/// let selector = tl::parse_query_selector("div#test");
61///
62/// match selector {
63/// Some(Selector::And(left, right)) => {
64/// assert!(matches!(&*left, Selector::Tag(b"div")));
65/// assert!(matches!(&*right, Selector::Id(b"test")));
66/// },
67/// _ => unreachable!()
68/// }
69/// ```
70pub fn parse_query_selector(input: &str) -> Option<Selector<'_>> {
71 let selector = queryselector::Parser::new(input.as_bytes()).selector()?;
72 Some(selector)
73}
74
75/// Parses the given input string and returns an owned, RAII guarded DOM
76///
77/// # Errors
78/// See [parse]
79///
80/// # Safety
81/// This uses `unsafe` code to create a self-referential-like struct.
82/// The given input string is first leaked and turned into raw pointer, and its lifetime will be promoted to 'static.
83/// Once `VDomGuard` goes out of scope, the string will be freed.
84/// It should not be possible to cause UB in its current form and might become a safe function in the future.
85pub unsafe fn parse_owned(input: String, options: ParserOptions) -> Result<VDomGuard, ParseError> {
86 VDomGuard::parse(input, options)
87}