GitHub PullRequestReviewCommentEvent at 2014-04-28 23:46:46
Repository: rust
Actor: kballard
Payload: {"comment":{"url":"https://api.github.com/repos/mozilla/rust/pulls/comments/12074208","id":12074208,"diff_hunk":"@@ -0,0 +1,145 @@\n+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT\n+// file at the top-level directory of this distribution and at\n+// http://rust-lang.org/COPYRIGHT.\n+//\n+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or\n+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license\n+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your\n+// option. This file may not be copied, modified, or distributed\n+// except according to those terms.\n+\n+//! HTML Escaping\n+//!\n+//! This module contains one unit-struct which can be used to HTML-escape a\n+//! string of text (for use in a format string).\n+\n+use std::fmt;\n+use std::str::{from_byte, MaybeOwned, Slice, Owned};\n+use entity;\n+\n+/// Wrapper struct which will emit the HTML-escaped version of the contained\n+/// string when passed to a format string.\n+pub struct Escape<'a>(pub &'a str);\n+\n+impl<'a> fmt::Show for Escape<'a> {\n+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {\n+        // Because the internet is always right, turns out there's not that many\n+        // characters to escape: http://stackoverflow.com/questions/7381974\n+        let Escape(s) = *self;\n+        let pile_o_bits = s.as_slice();\n+        let mut last = 0;\n+        for (i, ch) in s.bytes().enumerate() {\n+            let ent = match ch as char {\n+                '<' => \"&lt;\",\n+                '>' => \"&gt;\",\n+                '&' => \"&amp;\",\n+                '\\'' => \"&#39;\",\n+                '\"' => \"&quot;\",\n+                _ => continue\n+            };\n+            try!(fmt.buf.write(pile_o_bits.slice(last, i).as_bytes()));\n+            try!(fmt.buf.write(ent.as_bytes()));\n+            last = i + 1;\n+        }\n+\n+        if last < s.len() {\n+            try!(fmt.buf.write(pile_o_bits.slice_from(last).as_bytes()));\n+        }\n+        Ok(())\n+    }\n+}\n+\n+/// Wrapper struct which will unescape HTML entities in the contained\n+/// string when passed to a format string.\n+pub struct Unescape<'a>(pub &'a str);\n+\n+impl<'a> fmt::Show for Unescape<'a> {\n+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {\n+        let Unescape(s) = *self;\n+        let pile_o_bits = s.as_slice();\n+        let mut last = 0;\n+        let mut iter = s.bytes().enumerate();\n+        for (i, ch) in iter {\n+            match ch as char {\n+                '&' => {\n+                    try!(fmt.buf.write(pile_o_bits.slice(last, i).as_bytes()));\n+                    let (esc, n) = unescape_entity(s.bytes().skip(i+1));\n+\n+\n+                    try!(write!(fmt.buf, \"{}\", esc));\n+                    last = i + n;","path":"src/libhtml/fmt.rs","position":70,"original_position":70,"commit_id":"c879bf0df7ae37461ea6c380ddac1ceb70bb6e27","original_commit_id":"c879bf0df7ae37461ea6c380ddac1ceb70bb6e27","user":{"login":"kballard","id":714,"avatar_url":"https://avatars.githubusercontent.com/u/714?","gravatar_id":"6451ee8093c9cedc94f6c813b4dde2c5","url":"https://api.github.com/users/kballard","html_url":"https://github.com/kballard","followers_url":"https://api.github.com/users/kballard/followers","following_url":"https://api.github.com/users/kballard/following{/other_user}","gists_url":"https://api.github.com/users/kballard/gists{/gist_id}","starred_url":"https://api.github.com/users/kballard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kballard/subscriptions","organizations_url":"https://api.github.com/users/kballard/orgs","repos_url":"https://api.github.com/users/kballard/repos","events_url":"https://api.github.com/users/kballard/events{/privacy}","received_events_url":"https://api.github.com/users/kballard/received_events","type":"User","site_admin":false},"body":"This is likely to behave unexpectedly if you have malformed entity that looks something like `&a&b;`. Where \"behave unexpectedly\" will likely manifest as a failure on `pile.o_bits.slice(last, i)` where `last > i`.\r\n\r\nInstead, you should ditch the `for` loop and spin the iterator manually. You can then just pass the iterator directly to `unescape_entity()` instead of creating a new one, and it will consume everything up to (and including) the trailing `;`.","created_at":"2014-04-28T23:46:46Z","updated_at":"2014-04-28T23:46:46Z","html_url":"https://github.com/mozilla/rust/pull/13831#discussion_r12074208","pull_request_url":"https://api.github.com/repos/mozilla/rust/pulls/13831","_links":{"self":{"href":"https://api.github.com/repos/mozilla/rust/pulls/comments/12074208"},"html":{"href":"https://github.com/mozilla/rust/pull/13831#discussion_r12074208"},"pull_request":{"href":"https://api.github.com/repos/mozilla/rust/pulls/13831"}}}}