There certainly are many fast paths in the String implementation for known-ASCII contents. Unfortunately, knowing that your string is ASCII is not quite good enough for O(1) integer indexing into Characters because the ASCII string "\r\n" (CR+LF = 2 ASCII chars) becomes a single grapheme cluster according to the Unicode rules:
let str = "\r\n"
str.count // 1
str.utf8.count // 2
I don't know how String handles this internally. Maybe @David_Smith can answer this?
But regardless of the String-internal optimizations, what I wanted to say was that any fast paths the implementation can take for the hypothetical str[3...4], it should also be able to take for str.dropFirst(3).prefix(2), so both variants should be equally fast (except for the creation of the intermediate Substring due to the chaining of two operations).