I've changed this from mstring to char[] and re-upped the importance. Using dchar[] is constantly a pain in the ass, mostly because most other D code (and most system APIs) use char[]. Using char[] to represent strings still allows for all valid Unicode strings at the cost of slicing and indexing becoming an O(n) operation. But given that strings are immutable, their lengths can be known in advance, and their validity only has to be checked once. As long as the language sees it as a sequence of UTF-32 codepoints..
I did also give one of the record schemes some thought, but I have a feeling they'd be more trouble than they're worth, because although they save memory and offer O(1) slicing and indexing, they are a nonstandard encoding and would have to be transcoded for use with virtually all other libraries.