Avoid un-necessary decode in startsWith/endsWith

As requested in #2503.

Perhaps it's overkill?
Hum... That's true but:
1. It's consistent with what you'd get with find anyways.
2. The code is borderline wrong anyways: `needle[0..1]` is an invalid UTF sequence to begin with. As for the "character" `needle[0]`, while it caries an integral value that is a valid codepoint, isn't *technically* a codepoint when packaged in a `char`.

Maybe a better test of what I wanted to express here was:
```D
assert(!"é".startsWith('Ã')); //"é" == [0xC3, 0xA9] && 'Ã' == 0xC3
```
A more "ambiguous" test is:
```D
"é".startsWith(cast(char)'é');
```
*should* this return true or false? I don't *think* so, but `"é".front == cast(char)'é'` *will* return true. That said, *if* we want to cover this, then `startsWith` simply *can't* be nothrow, as there will always be a run-time condition that will require decoding...