2

I'm trying to write a simple function to escape HTML text (yes I know there are crates). Something like this:

fn escape(s: &str) -> String {
    s.chars().flat_map(|c| {
        match c {
            '<' => ['&', 'l', 't'].iter(),
            '>' => ['&', 'g', 't'].iter(),
            '"' => ['&', 'q', 'u', 'o', 't'].iter(),
            '\'' => ['&', 'a', 'p', 'o', 's'].iter(),
            '&' => ['&', 'a', 'm', 'p'].iter(),
            c => std::iter::once(c),
        }
    }).collect()
}

But it doesn't work, because the return types are different for the different arms:

expected struct `std::slice::Iter`, found struct `std::iter::Once`

I've tried many many things, but everything I try has some small problem:

  • You can't do "&lt".chars() and c.chars() because char doesn't implement chars().
  • You can't do [c].iter() because c is on the stack and iter() only keeps a reference to it - I couldn't work out how to move stuff into the iterator (I guess you probably can't).

Is there some sensible solution (that doesn't involve .to_string()).

Timmmm
  • 88,195
  • 71
  • 364
  • 509
  • There's always the simple solution of using a good old `for` loop and `push` and `push_str`... It looks cleaner to me than abusing `iter` and `flat_map` – Denys Séguret Aug 28 '19 at 13:49
  • That is a good point! Still, I'll leave the question open because I feel like you *should* be able to do this somehow. – Timmmm Aug 28 '19 at 13:52
  • 1
    why not just `[c].iter()` ? – Stargateur Aug 28 '19 at 13:52
  • @Stargateur: Read the question – Timmmm Aug 28 '19 at 14:04
  • 1
    @Stargateur who would own `c`? `iter()` just uses references, the other ones are fine because they are constants. – mcarton Aug 28 '19 at 14:04
  • 1
    It looks like your question might be answered by the answers of [Conditionally iterate over one of several possible iterators](https://stackoverflow.com/q/29760668/155423). If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Aug 28 '19 at 14:05
  • 1
    Re abusing `flat_map` - check the [str::escape_default](https://doc.rust-lang.org/std/primitive.str.html#method.escape_default) source for example -> `FlatMap`. – zrzka Aug 28 '19 at 14:11
  • @zrzka You're right. – Denys Séguret Aug 28 '19 at 14:18
  • https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b727eda5c09c1eda329f873cd625a281 – Stargateur Aug 28 '19 at 14:47
  • Some copy must be involved since the function is `fn(&str) -> String` – edwardw Aug 28 '19 at 14:49

0 Answers0