<h3>string type conversions</h3>

Legend:

  *  <b>copy</b> - get a freshly allocated copy of the data (possibly in a different format, i.e. not bit-for-bit the same)
  *  <b>alias</b> - get a slice of the <em>exact same data</em>, without allocation
  *  <b>dstring</b> - read "dstring (or wstring)". Only big difference is that wstring has its own C string type with std.utf.toUTF16z

<h4>from string (or char[])</h4>

  *  <b>string -> string</b>: copy with <code>st.idup</code> or <code>std.utf.toUTF8(st)</code>
  *  <b>string -> dstring</b>: copy with <code>std.utf.toUTF32(st)</code> or <code>std.conv.to!dstring(st)</code>
  *  <b>dstring -> string</b>: copy with <code>std.utf.toUTF8(st)</code> or <code>std.conv.to!string(st)</code>
  *  <b>string -> char[]</b>: mutable copy with <code>st.dup</code>
  *  <b>string -> immutable(ubyte)[]</b>: alias with <code>std.string.representation(st)</code>
  *  <b>string -> C string</b>: copy with <code>std.string.toStringz(st)</code>
  *  <b>char[] -> string</b>: unsafe alias with <code>std.exception.assumeUnique(st)</code>

<h4>from "string literal"</h4>

  *  <b>string literal -> C string</b>: alias by using it where a C string is wanted, <code>const(char)* s = "string literal"</code>, <code>puts("hi")</code>
  *  <b>string -> C string</b>: if a string <em>definitely</em> came from a string literal, then alias it with (@safe doesn't like <code>st.ptr</code> which can be <code>null</code>)

<h4>from ubyte[]</h4>

  *  <b>ubyte[] -> char[]</b>: alias with <code>std.string.assumeUTF(st)</code>. asserts on invalid UTF in debug builds
  *  <b>ubyte[] -> char[]</b>: alias with <code>cast(char[]) st</code>. still @safe when qualifiers (like <code>const</code>) aren't discarded

<h4>from C string</h4>

  *  <b>C string -> string</b>: unsafe alias with <code>std.string.fromStringz(st)</code>

<h4>from char range</h4>

  *  <b>dchar range -> dstring</b>: copy with <code>std.array.array(st)</code>
  *  <b>dchar range -> dchar[]</b>: copy with <code>std.array.array(st)</code>
  *  <b>char range -> string</b>: same as above, but with autodecoding you'll easily get dchar where you expected char. Suppress that with <code>std.utf.byCodeUnit</code>, e.g. <code>string st = "hello".byCodeUnit.map!(c => c).array</code>, which would normally require <code>dstring st = ...</code>

<h4>on mutability</h4>

  *  read Spec - Type Qualifiers]
  *  <b>immutable(T)[] -> const(T)[]</b>: implicit conversion
  *  <b>immutable(T)* -> const(T)*</b>: implicit conversion
  *  <b>string -> char[]</b>: <code>st.dup</code>
  *  <b>string -> char*</b>: <code>cast(char*) std.string.toStringz(st)</code> (not but safe as <code>toStringz</code> always copies)

covers this in greater detail, with unit tests. may also be of interest.