Accept 0x and 0X prefixes
diff --git a/lib/src/int64.dart b/lib/src/int64.dart
index 9c2a88d..a1d65dc 100644
--- a/lib/src/int64.dart
+++ b/lib/src/int64.dart
@@ -114,15 +114,28 @@
   static Int64 _tryParse(String s, int radix) {
     // A radix-36 digit is 5.17 bits, so 10 digits can fit 52 bits, the
     // safe-integer range of a JavaScript Number.
-    if (s.length <= 10) _parseViaInt(s, radix);
+    if (s.length <= 10) return _parseViaInt(s, radix);
     s = s.trim();
+
+    // Try the fast path again. In the common case where no whitespace is
+    // trimmed, the test serves to guard the `codeUnitAt` references.
+    if (s.length <= 10) return _parseViaInt(s, radix);
+
+    bool negative = false;
+    int start = 0;
+    int ch = s.codeUnitAt(start);
+    negative = ch == 45; /* '-' */
+    if (negative || ch == 43 /* '+' */) start++;
+
     if (radix == null) {
-      if (s.startsWith('-0x')) return _parseRadix(s, true, 4, 16);
-      if (s.startsWith('0x')) return _parseRadix(s, false, 3, 16);
+      if (s.codeUnitAt(start) == 48 /* '0' */ &&
+          s.codeUnitAt(start + 1) | 32 == 120 /* 'x' or 'X' */) {
+        return _parseRadix(s, negative, start + 2, 16);
+      }
       radix = 10;
     }
-    if (s.startsWith('-')) return _parseRadix(s, true, 1, radix);
-    return _parseRadix(s, false, 0, radix);
+
+    return _parseRadix(s, negative, start, radix);
   }
 
   static Int64 _parseViaInt(String s, int radix) {
diff --git a/test/int64_test.dart b/test/int64_test.dart
index 76693f6..3f3f21f 100644
--- a/test/int64_test.dart
+++ b/test/int64_test.dart
@@ -772,6 +772,78 @@
   });
 
   group("parse", () {
+    test("parse", () {
+      checkInt(int x) {
+        expect(Int64.parse('$x'), new Int64(x));
+        expect(Int64.parse('$x', radix: 10), new Int64(x));
+        expect(Int64.tryParse('$x'), new Int64(x));
+        expect(Int64.tryParse('$x', radix: 10), new Int64(x));
+      }
+
+      checkInt(0);
+      checkInt(1);
+      checkInt(-1);
+      checkInt(1000);
+      checkInt(12345678);
+      checkInt(-12345678);
+      checkInt(2147483647);
+      checkInt(2147483648);
+      checkInt(-2147483647);
+      checkInt(-2147483648);
+      checkInt(4294967295);
+      checkInt(4294967296);
+      checkInt(-4294967295);
+      checkInt(-4294967296);
+      checkInt(1000000000000);
+      checkInt(-1000000000000);
+      checkInt(1000000000001);
+      checkInt(-1000000000001);
+      expect(() => Int64.parseRadix('xyzzy', -1), throwsArgumentError);
+      expect(() => Int64.parseRadix('plugh', 10), throwsFormatException);
+
+      expect(() => Int64.parse('plugh', radix: 10), throwsFormatException);
+      expect(Int64.tryParse('plugh', radix: 10), isNull);
+
+      Int64 big = new Int64(1000000000000);
+      expect(Int64.tryParse('1000000000000'), big);
+      expect(Int64.tryParse('1000000000001'), big + 1);
+      expect(Int64.tryParse('+1000000000000'), big);
+      expect(Int64.tryParse('+1000000000001'), big + 1);
+      expect(Int64.tryParse('-1000000000000'), -big);
+      expect(Int64.tryParse('-1000000000001'), -(big + 1));
+
+      expect(Int64.tryParse('  1000000000000   '), big);
+      expect(Int64.tryParse('  1000000000001   '), big + 1);
+      expect(Int64.tryParse('  +1000000000000  '), big);
+      expect(Int64.tryParse('  +1000000000001  '), big + 1);
+      expect(Int64.tryParse('  -1000000000000  '), -big);
+      expect(Int64.tryParse('  -1000000000001  '), -(big + 1));
+      expect(Int64.tryParse('  + 1000000000000  '), isNull);
+      expect(Int64.tryParse('  + 1000000000001  '), isNull);
+      expect(Int64.tryParse('  - 1000000000000  '), isNull);
+      expect(Int64.tryParse('  - 1000000000001  '), isNull);
+
+      checkHex(String s, Int64 value) {
+        check(String s, Int64 value) {
+          expect(Int64.tryParse(s), value,
+              reason: '"$s" should parse to $value');
+        }
+
+        check(s.toLowerCase(), value);
+        check(s.toUpperCase(), value);
+        check(' ${s.toUpperCase()} ', value);
+        check(' ${s.toLowerCase()} ', value);
+      }
+
+      Int64 big2 = new Int64(0x1000000000);
+      checkHex('0x1000000000', big2);
+      checkHex('0x1000000001', big2 + 1);
+      checkHex('+0x1000000000', big2);
+      checkHex('+0x1000000001', big2 + 1);
+      checkHex('-0x1000000000', -big2);
+      checkHex('-0x1000000001', -(big2 + 1));
+    });
+
     test("parseRadix10", () {
       checkInt(int x) {
         expect(Int64.parseRadix('$x', 10), new Int64(x));
@@ -795,6 +867,10 @@
       checkInt(4294967296);
       checkInt(-4294967295);
       checkInt(-4294967296);
+      checkInt(1000000000000);
+      checkInt(-1000000000000);
+      checkInt(1000000000001);
+      checkInt(-1000000000001);
       expect(() => Int64.parseRadix('xyzzy', -1), throwsArgumentError);
       expect(() => Int64.parseRadix('plugh', 10), throwsFormatException);