// COPY: Copied from libcore.net.UriCodec
 /// <param name="convertPlus">true to convert '+' to ' '.</param>
 public static string Decode(string s, bool convertPlus, Encoding charset)
 {
     if (s.IndexOf('%') == -1 && (!convertPlus || s.IndexOf('+') == -1))
     {
         return s;
     }
     StringBuilder result = new StringBuilder(s.Length);
     ByteArrayOutputStream @out = new ByteArrayOutputStream();
     for (int i = 0; i < s.Length; )
     {
         char c = s[i];
         if (c == '%')
         {
             do
             {
                 if (i + 2 >= s.Length)
                 {
                     throw new ArgumentException("Incomplete % sequence at: " + i);
                 }
                 int d1 = HexToInt(s[i + 1]);
                 int d2 = HexToInt(s[i + 2]);
                 if (d1 == -1 || d2 == -1)
                 {
                     throw new ArgumentException("Invalid % sequence " + Sharpen.Runtime.Substring(s, 
                         i, i + 3) + " at " + i);
                 }
                 @out.Write(unchecked((byte)((d1 << 4) + d2)));
                 i += 3;
             }
             while (i < s.Length && s[i] == '%');
             result.Append(charset.GetString(@out.ToByteArray()));
             @out.Reset();
         }
         else
         {
             if (convertPlus && c == '+')
             {
                 c = ' ';
             }
             result.Append(c);
             i++;
         }
     }
     return result.ToString();
 }