1  // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
  2  // file at the top-level directory of this distribution and at
  3  // http://rust-lang.org/COPYRIGHT.
  4  //
  5  // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
  6  // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
  7  // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
  8  // option. This file may not be copied, modified, or distributed
  9  // except according to those terms.
 10  
 11  //! HTML Escaping
 12  //!
 13  //! This module contains one unit-struct which can be used to HTML-escape a
 14  //! string of text (for use in a format string).
 15  
 16  use std::fmt;
 17  
 18  /// Wrapper struct which will emit the HTML-escaped version of the contained
 19  /// string when passed to a format string.
 20  pub struct Escape<'a>(pub &'a str);
 21  
 22  impl<'a> fmt::Show for Escape<'a> {
 23      fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 24          // Because the internet is always right, turns out there's not that many
 25          // characters to escape: http://stackoverflow.com/questions/7381974
 26          let Escape(s) = *self;
 27          let pile_o_bits = s.as_slice();
 28          let mut last = 0;
 29          for (i, ch) in s.bytes().enumerate() {
 30              match ch as char {
 31                  '<' | '>' | '&' | '\'' | '"' => {
 32                      try!(fmt.buf.write(pile_o_bits.slice(last, i).as_bytes()));
 33                      let s = match ch as char {
 34                          '>' => ">",
 35                          '<' => "<",
 36                          '&' => "&",
 37                          '\'' => "'",
 38                          '"' => """,
 39                          _ => unreachable!()
 40                      };
 41                      try!(fmt.buf.write(s.as_bytes()));
 42                      last = i + 1;
 43                  }
 44                  _ => {}
 45              }
 46          }
 47  
 48          if last < s.len() {
 49              try!(fmt.buf.write(pile_o_bits.slice_from(last).as_bytes()));
 50          }
 51          Ok(())
 52      }
 53  }