#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(not(docsrs), no_std)]
#![deny(elided_lifetimes_in_paths)]
#![deny(unreachable_pub)]
#![deny(missing_docs)]
#![doc = include_str!("../README.md")]
use core::fmt;
mod ascii_str;
mod html;
#[derive(Debug, Clone, Copy, Default)]
pub struct Html;
#[derive(Debug, Clone, Copy, Default)]
pub struct Text;
pub trait Escaper {
fn write_escaped<W: fmt::Write>(&self, dest: W, string: &str) -> fmt::Result;
}
impl Escaper for Html {
#[inline]
fn write_escaped<W: fmt::Write>(&self, dest: W, string: &str) -> fmt::Result {
html::write_escaped_str(dest, string)
}
}
impl Escaper for Text {
#[inline]
fn write_escaped<W: fmt::Write>(&self, mut dest: W, string: &str) -> fmt::Result {
dest.write_str(string)
}
}
#[derive(Debug, Clone, Copy)]
pub struct Escaped<'a, E: Escaper> {
string: &'a str,
escaper: E,
}
impl<E: Escaper> fmt::Display for Escaped<'_, E> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.escaper.write_escaped(f, self.string)
}
}
#[inline]
pub fn escape<E: Escaper>(string: &str, escaper: E) -> Escaped<'_, E> {
Escaped { string, escaper }
}
#[inline]
pub fn escape_html(dest: impl fmt::Write, src: &str) -> fmt::Result {
html::write_escaped_str(dest, src)
}
pub fn escape_html_char(dest: impl fmt::Write, c: char) -> fmt::Result {
html::write_escaped_char(dest, c)
}
#[cfg(test)]
mod tests {
extern crate std;
use std::string::ToString;
use super::*;
#[test]
fn test_escape() {
assert_eq!(escape("", Html).to_string(), "");
assert_eq!(escape("<&>", Html).to_string(), "<&>");
assert_eq!(escape("bla&", Html).to_string(), "bla&");
assert_eq!(escape("<foo", Html).to_string(), "<foo");
assert_eq!(escape("bla&h", Html).to_string(), "bla&h");
}
}