Remove unused boost dep from Conv.h
[folly.git] / folly / Conv.h
1 /*
2  * Copyright 2017 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * Converts anything to anything, with an emphasis on performance and
19  * safety.
20  *
21  * @author Andrei Alexandrescu (andrei.alexandrescu@fb.com)
22  */
23
24 #pragma once
25
26 #include <algorithm>
27 #include <cctype>
28 #include <climits>
29 #include <cstddef>
30 #include <limits>
31 #include <stdexcept>
32 #include <string>
33 #include <tuple>
34 #include <type_traits>
35 #include <typeinfo>
36 #include <utility>
37
38 #include <double-conversion/double-conversion.h> // V8 JavaScript implementation
39
40 #include <folly/Demangle.h>
41 #include <folly/Expected.h>
42 #include <folly/FBString.h>
43 #include <folly/Likely.h>
44 #include <folly/Range.h>
45 #include <folly/Traits.h>
46 #include <folly/Unit.h>
47 #include <folly/portability/Math.h>
48
49 namespace folly {
50
51 // Keep this in sync with kErrorStrings in Conv.cpp
52 enum class ConversionCode : unsigned char {
53   SUCCESS,
54   EMPTY_INPUT_STRING,
55   NO_DIGITS,
56   BOOL_OVERFLOW,
57   BOOL_INVALID_VALUE,
58   NON_DIGIT_CHAR,
59   INVALID_LEADING_CHAR,
60   POSITIVE_OVERFLOW,
61   NEGATIVE_OVERFLOW,
62   STRING_TO_FLOAT_ERROR,
63   NON_WHITESPACE_AFTER_END,
64   ARITH_POSITIVE_OVERFLOW,
65   ARITH_NEGATIVE_OVERFLOW,
66   ARITH_LOSS_OF_PRECISION,
67   NUM_ERROR_CODES, // has to be the last entry
68 };
69
70 struct ConversionErrorBase : std::range_error {
71   using std::range_error::range_error;
72 };
73
74 class ConversionError : public ConversionErrorBase {
75  public:
76   ConversionError(const std::string& str, ConversionCode code)
77       : ConversionErrorBase(str), code_(code) {}
78
79   ConversionError(const char* str, ConversionCode code)
80       : ConversionErrorBase(str), code_(code) {}
81
82   ConversionCode errorCode() const {
83     return code_;
84   }
85
86  private:
87   ConversionCode code_;
88 };
89
90 /*******************************************************************************
91  * Custom Error Translation
92  *
93  * Your overloaded parseTo() function can return a custom error code on failure.
94  * ::folly::to() will call makeConversionError to translate that error code into
95  * an object to throw. makeConversionError is found by argument-dependent
96  * lookup. It should have this signature:
97  *
98  * namespace other_namespace {
99  * enum YourErrorCode { BAD_ERROR, WORSE_ERROR };
100  *
101  * struct YourConversionError : ConversionErrorBase {
102  *   YourConversionError(const char* what) : ConversionErrorBase(what) {}
103  * };
104  *
105  * YourConversionError
106  * makeConversionError(YourErrorCode code, ::folly::StringPiece sp) {
107  *   ...
108  *   return YourConversionError(messageString);
109  * }
110  ******************************************************************************/
111 ConversionError makeConversionError(ConversionCode code, StringPiece sp);
112
113 namespace detail {
114 /**
115  * Enforce that the suffix following a number is made up only of whitespace.
116  */
117 inline ConversionCode enforceWhitespaceErr(StringPiece sp) {
118   for (auto c : sp) {
119     if (UNLIKELY(!std::isspace(c))) {
120       return ConversionCode::NON_WHITESPACE_AFTER_END;
121     }
122   }
123   return ConversionCode::SUCCESS;
124 }
125
126 /**
127  * Keep this implementation around for prettyToDouble().
128  */
129 inline void enforceWhitespace(StringPiece sp) {
130   auto err = enforceWhitespaceErr(sp);
131   if (err != ConversionCode::SUCCESS) {
132     throw makeConversionError(err, sp);
133   }
134 }
135 } // namespace detail
136
137 /**
138  * The identity conversion function.
139  * tryTo<T>(T) returns itself for all types T.
140  */
141 template <class Tgt, class Src>
142 typename std::enable_if<
143     std::is_same<Tgt, typename std::decay<Src>::type>::value,
144     Expected<Tgt, ConversionCode>>::type
145 tryTo(Src&& value) {
146   return std::forward<Src>(value);
147 }
148
149 template <class Tgt, class Src>
150 typename std::enable_if<
151     std::is_same<Tgt, typename std::decay<Src>::type>::value,
152     Tgt>::type
153 to(Src&& value) {
154   return std::forward<Src>(value);
155 }
156
157 /*******************************************************************************
158  * Arithmetic to boolean
159  ******************************************************************************/
160
161 /**
162  * Unchecked conversion from arithmetic to boolean. This is different from the
163  * other arithmetic conversions because we use the C convention of treating any
164  * non-zero value as true, instead of range checking.
165  */
166 template <class Tgt, class Src>
167 typename std::enable_if<
168     std::is_arithmetic<Src>::value && !std::is_same<Tgt, Src>::value &&
169         std::is_same<Tgt, bool>::value,
170     Expected<Tgt, ConversionCode>>::type
171 tryTo(const Src& value) {
172   return value != Src();
173 }
174
175 template <class Tgt, class Src>
176 typename std::enable_if<
177     std::is_arithmetic<Src>::value && !std::is_same<Tgt, Src>::value &&
178         std::is_same<Tgt, bool>::value,
179     Tgt>::type
180 to(const Src& value) {
181   return value != Src();
182 }
183
184 /*******************************************************************************
185  * Anything to string
186  ******************************************************************************/
187
188 namespace detail {
189
190 #ifdef _MSC_VER
191 // MSVC can't quite figure out the LastElementImpl::call() stuff
192 // in the base implementation, so we have to use tuples instead,
193 // which result in significantly more templates being compiled,
194 // though the runtime performance is the same.
195
196 template <typename... Ts>
197 auto getLastElement(Ts&&... ts) -> decltype(
198     std::get<sizeof...(Ts)-1>(std::forward_as_tuple(std::forward<Ts>(ts)...))) {
199   return std::get<sizeof...(Ts)-1>(
200       std::forward_as_tuple(std::forward<Ts>(ts)...));
201 }
202
203 inline void getLastElement() {}
204
205 template <size_t size, typename... Ts>
206 struct LastElementType : std::tuple_element<size - 1, std::tuple<Ts...>> {};
207
208 template <>
209 struct LastElementType<0> {
210   using type = void;
211 };
212
213 template <class... Ts>
214 struct LastElement
215     : std::decay<typename LastElementType<sizeof...(Ts), Ts...>::type> {};
216 #else
217 template <typename... Ts>
218 struct LastElementImpl {
219   static void call(Ignored<Ts>...) {}
220 };
221
222 template <typename Head, typename... Ts>
223 struct LastElementImpl<Head, Ts...> {
224   template <typename Last>
225   static Last call(Ignored<Ts>..., Last&& last) {
226     return std::forward<Last>(last);
227   }
228 };
229
230 template <typename... Ts>
231 auto getLastElement(const Ts&... ts)
232     -> decltype(LastElementImpl<Ts...>::call(ts...)) {
233   return LastElementImpl<Ts...>::call(ts...);
234 }
235
236 template <class... Ts>
237 struct LastElement : std::decay<decltype(
238                          LastElementImpl<Ts...>::call(std::declval<Ts>()...))> {
239 };
240 #endif
241
242 } // namespace detail
243
244 /*******************************************************************************
245  * Conversions from integral types to string types.
246  ******************************************************************************/
247
248 #if FOLLY_HAVE_INT128_T
249 namespace detail {
250
251 template <typename IntegerType>
252 constexpr unsigned int
253 digitsEnough() {
254   return (unsigned int)(ceil(sizeof(IntegerType) * CHAR_BIT * M_LN2 / M_LN10));
255 }
256
257 inline size_t
258 unsafeTelescope128(char * buffer, size_t room, unsigned __int128 x) {
259   typedef unsigned __int128 Usrc;
260   size_t p = room - 1;
261
262   while (x >= (Usrc(1) << 64)) { // Using 128-bit division while needed
263     const auto y = x / 10;
264     const auto digit = x % 10;
265
266     buffer[p--] = '0' + digit;
267     x = y;
268   }
269
270   uint64_t xx = x; // Moving to faster 64-bit division thereafter
271
272   while (xx >= 10) {
273     const auto y = xx / 10ULL;
274     const auto digit = xx % 10ULL;
275
276     buffer[p--] = '0' + digit;
277     xx = y;
278   }
279
280   buffer[p] = '0' + xx;
281
282   return p;
283 }
284
285 } // namespace detail
286 #endif
287
288 /**
289  * Returns the number of digits in the base 10 representation of an
290  * uint64_t. Useful for preallocating buffers and such. It's also used
291  * internally, see below. Measurements suggest that defining a
292  * separate overload for 32-bit integers is not worthwhile.
293  */
294
295 inline uint32_t digits10(uint64_t v) {
296 #ifdef __x86_64__
297
298   // For this arch we can get a little help from specialized CPU instructions
299   // which can count leading zeroes; 64 minus that is appx. log (base 2).
300   // Use that to approximate base-10 digits (log_10) and then adjust if needed.
301
302   // 10^i, defined for i 0 through 19.
303   // This is 20 * 8 == 160 bytes, which fits neatly into 5 cache lines
304   // (assuming a cache line size of 64).
305   alignas(64) static const uint64_t powersOf10[20] = {
306       1,
307       10,
308       100,
309       1000,
310       10000,
311       100000,
312       1000000,
313       10000000,
314       100000000,
315       1000000000,
316       10000000000,
317       100000000000,
318       1000000000000,
319       10000000000000,
320       100000000000000,
321       1000000000000000,
322       10000000000000000,
323       100000000000000000,
324       1000000000000000000,
325       10000000000000000000UL,
326   };
327
328   // "count leading zeroes" operation not valid; for 0; special case this.
329   if UNLIKELY (! v) {
330     return 1;
331   }
332
333   // bits is in the ballpark of log_2(v).
334   const uint8_t leadingZeroes = __builtin_clzll(v);
335   const auto bits = 63 - leadingZeroes;
336
337   // approximate log_10(v) == log_10(2) * bits.
338   // Integer magic below: 77/256 is appx. 0.3010 (log_10(2)).
339   // The +1 is to make this the ceiling of the log_10 estimate.
340   const uint32_t minLength = 1 + ((bits * 77) >> 8);
341
342   // return that log_10 lower bound, plus adjust if input >= 10^(that bound)
343   // in case there's a small error and we misjudged length.
344   return minLength + (uint32_t) (UNLIKELY (v >= powersOf10[minLength]));
345
346 #else
347
348   uint32_t result = 1;
349   for (;;) {
350     if (LIKELY(v < 10)) return result;
351     if (LIKELY(v < 100)) return result + 1;
352     if (LIKELY(v < 1000)) return result + 2;
353     if (LIKELY(v < 10000)) return result + 3;
354     // Skip ahead by 4 orders of magnitude
355     v /= 10000U;
356     result += 4;
357   }
358
359 #endif
360 }
361
362 /**
363  * Copies the ASCII base 10 representation of v into buffer and
364  * returns the number of bytes written. Does NOT append a \0. Assumes
365  * the buffer points to digits10(v) bytes of valid memory. Note that
366  * uint64 needs at most 20 bytes, uint32_t needs at most 10 bytes,
367  * uint16_t needs at most 5 bytes, and so on. Measurements suggest
368  * that defining a separate overload for 32-bit integers is not
369  * worthwhile.
370  *
371  * This primitive is unsafe because it makes the size assumption and
372  * because it does not add a terminating \0.
373  */
374
375 inline uint32_t uint64ToBufferUnsafe(uint64_t v, char *const buffer) {
376   auto const result = digits10(v);
377   // WARNING: using size_t or pointer arithmetic for pos slows down
378   // the loop below 20x. This is because several 32-bit ops can be
379   // done in parallel, but only fewer 64-bit ones.
380   uint32_t pos = result - 1;
381   while (v >= 10) {
382     // Keep these together so a peephole optimization "sees" them and
383     // computes them in one shot.
384     auto const q = v / 10;
385     auto const r = static_cast<char>(v % 10);
386     buffer[pos--] = '0' + r;
387     v = q;
388   }
389   // Last digit is trivial to handle
390   buffer[pos] = static_cast<char>(v) + '0';
391   return result;
392 }
393
394 /**
395  * A single char gets appended.
396  */
397 template <class Tgt>
398 void toAppend(char value, Tgt * result) {
399   *result += value;
400 }
401
402 template <class T>
403 constexpr typename std::enable_if<
404   std::is_same<T, char>::value,
405   size_t>::type
406 estimateSpaceNeeded(T) {
407   return 1;
408 }
409
410 template <size_t N>
411 constexpr size_t estimateSpaceNeeded(const char (&)[N]) {
412   return N;
413 }
414
415 /**
416  * Everything implicitly convertible to const char* gets appended.
417  */
418 template <class Tgt, class Src>
419 typename std::enable_if<
420   std::is_convertible<Src, const char*>::value
421   && IsSomeString<Tgt>::value>::type
422 toAppend(Src value, Tgt * result) {
423   // Treat null pointers like an empty string, as in:
424   // operator<<(std::ostream&, const char*).
425   const char* c = value;
426   if (c) {
427     result->append(value);
428   }
429 }
430
431 template <class Src>
432 typename std::enable_if<std::is_convertible<Src, const char*>::value, size_t>::
433     type
434     estimateSpaceNeeded(Src value) {
435   const char *c = value;
436   if (c) {
437     return folly::StringPiece(value).size();
438   };
439   return 0;
440 }
441
442 template <class Src>
443 typename std::enable_if<IsSomeString<Src>::value, size_t>::type
444 estimateSpaceNeeded(Src const& value) {
445   return value.size();
446 }
447
448 template <class Src>
449 typename std::enable_if<
450     std::is_convertible<Src, folly::StringPiece>::value &&
451         !IsSomeString<Src>::value &&
452         !std::is_convertible<Src, const char*>::value,
453     size_t>::type
454 estimateSpaceNeeded(Src value) {
455   return folly::StringPiece(value).size();
456 }
457
458 template <>
459 inline size_t estimateSpaceNeeded(std::nullptr_t /* value */) {
460   return 0;
461 }
462
463 template <class Src>
464 typename std::enable_if<
465   std::is_pointer<Src>::value &&
466   IsSomeString<std::remove_pointer<Src>>::value,
467   size_t>::type
468 estimateSpaceNeeded(Src value) {
469   return value->size();
470 }
471
472 /**
473  * Strings get appended, too.
474  */
475 template <class Tgt, class Src>
476 typename std::enable_if<
477   IsSomeString<Src>::value && IsSomeString<Tgt>::value>::type
478 toAppend(const Src& value, Tgt * result) {
479   result->append(value);
480 }
481
482 /**
483  * and StringPiece objects too
484  */
485 template <class Tgt>
486 typename std::enable_if<
487    IsSomeString<Tgt>::value>::type
488 toAppend(StringPiece value, Tgt * result) {
489   result->append(value.data(), value.size());
490 }
491
492 /**
493  * There's no implicit conversion from fbstring to other string types,
494  * so make a specialization.
495  */
496 template <class Tgt>
497 typename std::enable_if<
498    IsSomeString<Tgt>::value>::type
499 toAppend(const fbstring& value, Tgt * result) {
500   result->append(value.data(), value.size());
501 }
502
503 #if FOLLY_HAVE_INT128_T
504 /**
505  * Special handling for 128 bit integers.
506  */
507
508 template <class Tgt>
509 void
510 toAppend(__int128 value, Tgt * result) {
511   typedef unsigned __int128 Usrc;
512   char buffer[detail::digitsEnough<unsigned __int128>() + 1];
513   size_t p;
514
515   if (value < 0) {
516     p = detail::unsafeTelescope128(buffer, sizeof(buffer), -Usrc(value));
517     buffer[--p] = '-';
518   } else {
519     p = detail::unsafeTelescope128(buffer, sizeof(buffer), value);
520   }
521
522   result->append(buffer + p, buffer + sizeof(buffer));
523 }
524
525 template <class Tgt>
526 void
527 toAppend(unsigned __int128 value, Tgt * result) {
528   char buffer[detail::digitsEnough<unsigned __int128>()];
529   size_t p;
530
531   p = detail::unsafeTelescope128(buffer, sizeof(buffer), value);
532
533   result->append(buffer + p, buffer + sizeof(buffer));
534 }
535
536 template <class T>
537 constexpr typename std::enable_if<
538   std::is_same<T, __int128>::value,
539   size_t>::type
540 estimateSpaceNeeded(T) {
541   return detail::digitsEnough<__int128>();
542 }
543
544 template <class T>
545 constexpr typename std::enable_if<
546   std::is_same<T, unsigned __int128>::value,
547   size_t>::type
548 estimateSpaceNeeded(T) {
549   return detail::digitsEnough<unsigned __int128>();
550 }
551
552 #endif
553
554 /**
555  * int32_t and int64_t to string (by appending) go through here. The
556  * result is APPENDED to a preexisting string passed as the second
557  * parameter. This should be efficient with fbstring because fbstring
558  * incurs no dynamic allocation below 23 bytes and no number has more
559  * than 22 bytes in its textual representation (20 for digits, one for
560  * sign, one for the terminating 0).
561  */
562 template <class Tgt, class Src>
563 typename std::enable_if<
564   std::is_integral<Src>::value && std::is_signed<Src>::value &&
565   IsSomeString<Tgt>::value && sizeof(Src) >= 4>::type
566 toAppend(Src value, Tgt * result) {
567   char buffer[20];
568   if (value < 0) {
569     result->push_back('-');
570     result->append(
571         buffer,
572         uint64ToBufferUnsafe(~static_cast<uint64_t>(value) + 1, buffer));
573   } else {
574     result->append(buffer, uint64ToBufferUnsafe(uint64_t(value), buffer));
575   }
576 }
577
578 template <class Src>
579 typename std::enable_if<
580   std::is_integral<Src>::value && std::is_signed<Src>::value
581   && sizeof(Src) >= 4 && sizeof(Src) < 16,
582   size_t>::type
583 estimateSpaceNeeded(Src value) {
584   if (value < 0) {
585     // When "value" is the smallest negative, negating it would evoke
586     // undefined behavior, so, instead of writing "-value" below, we write
587     // "~static_cast<uint64_t>(value) + 1"
588     return 1 + digits10(~static_cast<uint64_t>(value) + 1);
589   }
590
591   return digits10(static_cast<uint64_t>(value));
592 }
593
594 /**
595  * As above, but for uint32_t and uint64_t.
596  */
597 template <class Tgt, class Src>
598 typename std::enable_if<
599   std::is_integral<Src>::value && !std::is_signed<Src>::value
600   && IsSomeString<Tgt>::value && sizeof(Src) >= 4>::type
601 toAppend(Src value, Tgt * result) {
602   char buffer[20];
603   result->append(buffer, uint64ToBufferUnsafe(value, buffer));
604 }
605
606 template <class Src>
607 typename std::enable_if<
608   std::is_integral<Src>::value && !std::is_signed<Src>::value
609   && sizeof(Src) >= 4 && sizeof(Src) < 16,
610   size_t>::type
611 estimateSpaceNeeded(Src value) {
612   return digits10(value);
613 }
614
615 /**
616  * All small signed and unsigned integers to string go through 32-bit
617  * types int32_t and uint32_t, respectively.
618  */
619 template <class Tgt, class Src>
620 typename std::enable_if<
621   std::is_integral<Src>::value
622   && IsSomeString<Tgt>::value && sizeof(Src) < 4>::type
623 toAppend(Src value, Tgt * result) {
624   typedef typename
625     std::conditional<std::is_signed<Src>::value, int64_t, uint64_t>::type
626     Intermediate;
627   toAppend<Tgt>(static_cast<Intermediate>(value), result);
628 }
629
630 template <class Src>
631 typename std::enable_if<
632   std::is_integral<Src>::value
633   && sizeof(Src) < 4
634   && !std::is_same<Src, char>::value,
635   size_t>::type
636 estimateSpaceNeeded(Src value) {
637   typedef typename
638     std::conditional<std::is_signed<Src>::value, int64_t, uint64_t>::type
639     Intermediate;
640   return estimateSpaceNeeded(static_cast<Intermediate>(value));
641 }
642
643 /**
644  * Enumerated values get appended as integers.
645  */
646 template <class Tgt, class Src>
647 typename std::enable_if<
648   std::is_enum<Src>::value && IsSomeString<Tgt>::value>::type
649 toAppend(Src value, Tgt * result) {
650   toAppend(
651       static_cast<typename std::underlying_type<Src>::type>(value), result);
652 }
653
654 template <class Src>
655 typename std::enable_if<
656   std::is_enum<Src>::value, size_t>::type
657 estimateSpaceNeeded(Src value) {
658   return estimateSpaceNeeded(
659       static_cast<typename std::underlying_type<Src>::type>(value));
660 }
661
662 /*******************************************************************************
663  * Conversions from floating-point types to string types.
664  ******************************************************************************/
665
666 namespace detail {
667 constexpr int kConvMaxDecimalInShortestLow = -6;
668 constexpr int kConvMaxDecimalInShortestHigh = 21;
669 } // namespace detail
670
671 /** Wrapper around DoubleToStringConverter **/
672 template <class Tgt, class Src>
673 typename std::enable_if<
674   std::is_floating_point<Src>::value
675   && IsSomeString<Tgt>::value>::type
676 toAppend(
677   Src value,
678   Tgt * result,
679   double_conversion::DoubleToStringConverter::DtoaMode mode,
680   unsigned int numDigits) {
681   using namespace double_conversion;
682   DoubleToStringConverter
683     conv(DoubleToStringConverter::NO_FLAGS,
684          "Infinity", "NaN", 'E',
685          detail::kConvMaxDecimalInShortestLow,
686          detail::kConvMaxDecimalInShortestHigh,
687          6,   // max leading padding zeros
688          1);  // max trailing padding zeros
689   char buffer[256];
690   StringBuilder builder(buffer, sizeof(buffer));
691   switch (mode) {
692     case DoubleToStringConverter::SHORTEST:
693       conv.ToShortest(value, &builder);
694       break;
695     case DoubleToStringConverter::FIXED:
696       conv.ToFixed(value, int(numDigits), &builder);
697       break;
698     default:
699       CHECK(mode == DoubleToStringConverter::PRECISION);
700       conv.ToPrecision(value, int(numDigits), &builder);
701       break;
702   }
703   const size_t length = size_t(builder.position());
704   builder.Finalize();
705   result->append(buffer, length);
706 }
707
708 /**
709  * As above, but for floating point
710  */
711 template <class Tgt, class Src>
712 typename std::enable_if<
713   std::is_floating_point<Src>::value
714   && IsSomeString<Tgt>::value>::type
715 toAppend(Src value, Tgt * result) {
716   toAppend(
717     value, result, double_conversion::DoubleToStringConverter::SHORTEST, 0);
718 }
719
720 /**
721  * Upper bound of the length of the output from
722  * DoubleToStringConverter::ToShortest(double, StringBuilder*),
723  * as used in toAppend(double, string*).
724  */
725 template <class Src>
726 typename std::enable_if<
727   std::is_floating_point<Src>::value, size_t>::type
728 estimateSpaceNeeded(Src value) {
729   // kBase10MaximalLength is 17. We add 1 for decimal point,
730   // e.g. 10.0/9 is 17 digits and 18 characters, including the decimal point.
731   constexpr int kMaxMantissaSpace =
732     double_conversion::DoubleToStringConverter::kBase10MaximalLength + 1;
733   // strlen("E-") + digits10(numeric_limits<double>::max_exponent10)
734   constexpr int kMaxExponentSpace = 2 + 3;
735   static const int kMaxPositiveSpace = std::max({
736       // E.g. 1.1111111111111111E-100.
737       kMaxMantissaSpace + kMaxExponentSpace,
738       // E.g. 0.000001.1111111111111111, if kConvMaxDecimalInShortestLow is -6.
739       kMaxMantissaSpace - detail::kConvMaxDecimalInShortestLow,
740       // If kConvMaxDecimalInShortestHigh is 21, then 1e21 is the smallest
741       // number > 1 which ToShortest outputs in exponential notation,
742       // so 21 is the longest non-exponential number > 1.
743       detail::kConvMaxDecimalInShortestHigh
744     });
745   return size_t(
746       kMaxPositiveSpace +
747       (value < 0 ? 1 : 0)); // +1 for minus sign, if negative
748 }
749
750 /**
751  * This can be specialized, together with adding specialization
752  * for estimateSpaceNeed for your type, so that we allocate
753  * as much as you need instead of the default
754  */
755 template <class Src>
756 struct HasLengthEstimator : std::false_type {};
757
758 template <class Src>
759 constexpr typename std::enable_if<
760   !std::is_fundamental<Src>::value
761 #if FOLLY_HAVE_INT128_T
762   // On OSX 10.10, is_fundamental<__int128> is false :-O
763   && !std::is_same<__int128, Src>::value
764   && !std::is_same<unsigned __int128, Src>::value
765 #endif
766   && !IsSomeString<Src>::value
767   && !std::is_convertible<Src, const char*>::value
768   && !std::is_convertible<Src, StringPiece>::value
769   && !std::is_enum<Src>::value
770   && !HasLengthEstimator<Src>::value,
771   size_t>::type
772 estimateSpaceNeeded(const Src&) {
773   return sizeof(Src) + 1; // dumbest best effort ever?
774 }
775
776 namespace detail {
777
778 template <class Tgt>
779 typename std::enable_if<IsSomeString<Tgt>::value, size_t>::type
780 estimateSpaceToReserve(size_t sofar, Tgt*) {
781   return sofar;
782 }
783
784 template <class T, class... Ts>
785 size_t estimateSpaceToReserve(size_t sofar, const T& v, const Ts&... vs) {
786   return estimateSpaceToReserve(sofar + estimateSpaceNeeded(v), vs...);
787 }
788
789 template <class... Ts>
790 void reserveInTarget(const Ts&...vs) {
791   getLastElement(vs...)->reserve(estimateSpaceToReserve(0, vs...));
792 }
793
794 template <class Delimiter, class... Ts>
795 void reserveInTargetDelim(const Delimiter& d, const Ts&...vs) {
796   static_assert(sizeof...(vs) >= 2, "Needs at least 2 args");
797   size_t fordelim = (sizeof...(vs) - 2) *
798       estimateSpaceToReserve(0, d, static_cast<std::string*>(nullptr));
799   getLastElement(vs...)->reserve(estimateSpaceToReserve(fordelim, vs...));
800 }
801
802 /**
803  * Variadic base case: append one element
804  */
805 template <class T, class Tgt>
806 typename std::enable_if<
807   IsSomeString<typename std::remove_pointer<Tgt>::type>
808   ::value>::type
809 toAppendStrImpl(const T& v, Tgt result) {
810   toAppend(v, result);
811 }
812
813 template <class T, class... Ts>
814 typename std::enable_if<
815     sizeof...(Ts) >= 2 &&
816     IsSomeString<typename std::remove_pointer<
817         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
818 toAppendStrImpl(const T& v, const Ts&... vs) {
819   toAppend(v, getLastElement(vs...));
820   toAppendStrImpl(vs...);
821 }
822
823 template <class Delimiter, class T, class Tgt>
824 typename std::enable_if<
825     IsSomeString<typename std::remove_pointer<Tgt>::type>::value>::type
826 toAppendDelimStrImpl(const Delimiter& /* delim */, const T& v, Tgt result) {
827   toAppend(v, result);
828 }
829
830 template <class Delimiter, class T, class... Ts>
831 typename std::enable_if<
832     sizeof...(Ts) >= 2 &&
833     IsSomeString<typename std::remove_pointer<
834         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
835 toAppendDelimStrImpl(const Delimiter& delim, const T& v, const Ts&... vs) {
836   // we are really careful here, calling toAppend with just one element does
837   // not try to estimate space needed (as we already did that). If we call
838   // toAppend(v, delim, ....) we would do unnecesary size calculation
839   toAppend(v, detail::getLastElement(vs...));
840   toAppend(delim, detail::getLastElement(vs...));
841   toAppendDelimStrImpl(delim, vs...);
842 }
843 } // namespace detail
844
845 /**
846  * Variadic conversion to string. Appends each element in turn.
847  * If we have two or more things to append, we it will not reserve
848  * the space for them and will depend on strings exponential growth.
849  * If you just append once consider using toAppendFit which reserves
850  * the space needed (but does not have exponential as a result).
851  *
852  * Custom implementations of toAppend() can be provided in the same namespace as
853  * the type to customize printing. estimateSpaceNeed() may also be provided to
854  * avoid reallocations in toAppendFit():
855  *
856  * namespace other_namespace {
857  *
858  * template <class String>
859  * void toAppend(const OtherType&, String* out);
860  *
861  * // optional
862  * size_t estimateSpaceNeeded(const OtherType&);
863  *
864  * }
865  */
866 template <class... Ts>
867 typename std::enable_if<
868     sizeof...(Ts) >= 3 &&
869     IsSomeString<typename std::remove_pointer<
870         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
871 toAppend(const Ts&... vs) {
872   ::folly::detail::toAppendStrImpl(vs...);
873 }
874
875 #ifdef _MSC_VER
876 // Special case pid_t on MSVC, because it's a void* rather than an
877 // integral type. We can't do a global special case because this is already
878 // dangerous enough (as most pointers will implicitly convert to a void*)
879 // just doing it for MSVC.
880 template <class Tgt>
881 void toAppend(const pid_t a, Tgt* res) {
882   toAppend(uint64_t(a), res);
883 }
884 #endif
885
886 /**
887  * Special version of the call that preallocates exaclty as much memory
888  * as need for arguments to be stored in target. This means we are
889  * not doing exponential growth when we append. If you are using it
890  * in a loop you are aiming at your foot with a big perf-destroying
891  * bazooka.
892  * On the other hand if you are appending to a string once, this
893  * will probably save a few calls to malloc.
894  */
895 template <class... Ts>
896 typename std::enable_if<IsSomeString<typename std::remove_pointer<
897     typename detail::LastElement<const Ts&...>::type>::type>::value>::type
898 toAppendFit(const Ts&... vs) {
899   ::folly::detail::reserveInTarget(vs...);
900   toAppend(vs...);
901 }
902
903 template <class Ts>
904 void toAppendFit(const Ts&) {}
905
906 /**
907  * Variadic base case: do nothing.
908  */
909 template <class Tgt>
910 typename std::enable_if<IsSomeString<Tgt>::value>::type toAppend(
911     Tgt* /* result */) {}
912
913 /**
914  * Variadic base case: do nothing.
915  */
916 template <class Delimiter, class Tgt>
917 typename std::enable_if<IsSomeString<Tgt>::value>::type toAppendDelim(
918     const Delimiter& /* delim */, Tgt* /* result */) {}
919
920 /**
921  * 1 element: same as toAppend.
922  */
923 template <class Delimiter, class T, class Tgt>
924 typename std::enable_if<IsSomeString<Tgt>::value>::type toAppendDelim(
925     const Delimiter& /* delim */, const T& v, Tgt* tgt) {
926   toAppend(v, tgt);
927 }
928
929 /**
930  * Append to string with a delimiter in between elements. Check out
931  * comments for toAppend for details about memory allocation.
932  */
933 template <class Delimiter, class... Ts>
934 typename std::enable_if<
935     sizeof...(Ts) >= 3 &&
936     IsSomeString<typename std::remove_pointer<
937         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
938 toAppendDelim(const Delimiter& delim, const Ts&... vs) {
939   detail::toAppendDelimStrImpl(delim, vs...);
940 }
941
942 /**
943  * Detail in comment for toAppendFit
944  */
945 template <class Delimiter, class... Ts>
946 typename std::enable_if<IsSomeString<typename std::remove_pointer<
947     typename detail::LastElement<const Ts&...>::type>::type>::value>::type
948 toAppendDelimFit(const Delimiter& delim, const Ts&... vs) {
949   detail::reserveInTargetDelim(delim, vs...);
950   toAppendDelim(delim, vs...);
951 }
952
953 template <class De, class Ts>
954 void toAppendDelimFit(const De&, const Ts&) {}
955
956 /**
957  * to<SomeString>(v1, v2, ...) uses toAppend() (see below) as back-end
958  * for all types.
959  */
960 template <class Tgt, class... Ts>
961 typename std::enable_if<
962     IsSomeString<Tgt>::value &&
963         (sizeof...(Ts) != 1 ||
964          !std::is_same<Tgt, typename detail::LastElement<const Ts&...>::type>::
965              value),
966     Tgt>::type
967 to(const Ts&... vs) {
968   Tgt result;
969   toAppendFit(vs..., &result);
970   return result;
971 }
972
973 /**
974  * Special version of to<SomeString> for floating point. When calling
975  * folly::to<SomeString>(double), generic implementation above will
976  * firstly reserve 24 (or 25 when negative value) bytes. This will
977  * introduce a malloc call for most mainstream string implementations.
978  *
979  * But for most cases, a floating point doesn't need 24 (or 25) bytes to
980  * be converted as a string.
981  *
982  * This special version will not do string reserve.
983  */
984 template <class Tgt, class Src>
985 typename std::enable_if<
986     IsSomeString<Tgt>::value && std::is_floating_point<Src>::value,
987     Tgt>::type
988 to(Src value) {
989   Tgt result;
990   toAppend(value, &result);
991   return result;
992 }
993
994 /**
995  * toDelim<SomeString>(SomeString str) returns itself.
996  */
997 template <class Tgt, class Delim, class Src>
998 typename std::enable_if<
999     IsSomeString<Tgt>::value &&
1000         std::is_same<Tgt, typename std::decay<Src>::type>::value,
1001     Tgt>::type
1002 toDelim(const Delim& /* delim */, Src&& value) {
1003   return std::forward<Src>(value);
1004 }
1005
1006 /**
1007  * toDelim<SomeString>(delim, v1, v2, ...) uses toAppendDelim() as
1008  * back-end for all types.
1009  */
1010 template <class Tgt, class Delim, class... Ts>
1011 typename std::enable_if<
1012     IsSomeString<Tgt>::value &&
1013         (sizeof...(Ts) != 1 ||
1014          !std::is_same<Tgt, typename detail::LastElement<const Ts&...>::type>::
1015              value),
1016     Tgt>::type
1017 toDelim(const Delim& delim, const Ts&... vs) {
1018   Tgt result;
1019   toAppendDelimFit(delim, vs..., &result);
1020   return result;
1021 }
1022
1023 /*******************************************************************************
1024  * Conversions from string types to integral types.
1025  ******************************************************************************/
1026
1027 namespace detail {
1028
1029 Expected<bool, ConversionCode> str_to_bool(StringPiece* src) noexcept;
1030
1031 template <typename T>
1032 Expected<T, ConversionCode> str_to_floating(StringPiece* src) noexcept;
1033
1034 extern template Expected<float, ConversionCode> str_to_floating<float>(
1035     StringPiece* src) noexcept;
1036 extern template Expected<double, ConversionCode> str_to_floating<double>(
1037     StringPiece* src) noexcept;
1038
1039 template <class Tgt>
1040 Expected<Tgt, ConversionCode> digits_to(const char* b, const char* e) noexcept;
1041
1042 extern template Expected<char, ConversionCode> digits_to<char>(
1043     const char*,
1044     const char*) noexcept;
1045 extern template Expected<signed char, ConversionCode> digits_to<signed char>(
1046     const char*,
1047     const char*) noexcept;
1048 extern template Expected<unsigned char, ConversionCode>
1049 digits_to<unsigned char>(const char*, const char*) noexcept;
1050
1051 extern template Expected<short, ConversionCode> digits_to<short>(
1052     const char*,
1053     const char*) noexcept;
1054 extern template Expected<unsigned short, ConversionCode>
1055 digits_to<unsigned short>(const char*, const char*) noexcept;
1056
1057 extern template Expected<int, ConversionCode> digits_to<int>(
1058     const char*,
1059     const char*) noexcept;
1060 extern template Expected<unsigned int, ConversionCode> digits_to<unsigned int>(
1061     const char*,
1062     const char*) noexcept;
1063
1064 extern template Expected<long, ConversionCode> digits_to<long>(
1065     const char*,
1066     const char*) noexcept;
1067 extern template Expected<unsigned long, ConversionCode>
1068 digits_to<unsigned long>(const char*, const char*) noexcept;
1069
1070 extern template Expected<long long, ConversionCode> digits_to<long long>(
1071     const char*,
1072     const char*) noexcept;
1073 extern template Expected<unsigned long long, ConversionCode>
1074 digits_to<unsigned long long>(const char*, const char*) noexcept;
1075
1076 #if FOLLY_HAVE_INT128_T
1077 extern template Expected<__int128, ConversionCode> digits_to<__int128>(
1078     const char*,
1079     const char*) noexcept;
1080 extern template Expected<unsigned __int128, ConversionCode>
1081 digits_to<unsigned __int128>(const char*, const char*) noexcept;
1082 #endif
1083
1084 template <class T>
1085 Expected<T, ConversionCode> str_to_integral(StringPiece* src) noexcept;
1086
1087 extern template Expected<char, ConversionCode> str_to_integral<char>(
1088     StringPiece* src) noexcept;
1089 extern template Expected<signed char, ConversionCode>
1090 str_to_integral<signed char>(StringPiece* src) noexcept;
1091 extern template Expected<unsigned char, ConversionCode>
1092 str_to_integral<unsigned char>(StringPiece* src) noexcept;
1093
1094 extern template Expected<short, ConversionCode> str_to_integral<short>(
1095     StringPiece* src) noexcept;
1096 extern template Expected<unsigned short, ConversionCode>
1097 str_to_integral<unsigned short>(StringPiece* src) noexcept;
1098
1099 extern template Expected<int, ConversionCode> str_to_integral<int>(
1100     StringPiece* src) noexcept;
1101 extern template Expected<unsigned int, ConversionCode>
1102 str_to_integral<unsigned int>(StringPiece* src) noexcept;
1103
1104 extern template Expected<long, ConversionCode> str_to_integral<long>(
1105     StringPiece* src) noexcept;
1106 extern template Expected<unsigned long, ConversionCode>
1107 str_to_integral<unsigned long>(StringPiece* src) noexcept;
1108
1109 extern template Expected<long long, ConversionCode> str_to_integral<long long>(
1110     StringPiece* src) noexcept;
1111 extern template Expected<unsigned long long, ConversionCode>
1112 str_to_integral<unsigned long long>(StringPiece* src) noexcept;
1113
1114 #if FOLLY_HAVE_INT128_T
1115 extern template Expected<__int128, ConversionCode> str_to_integral<__int128>(
1116     StringPiece* src) noexcept;
1117 extern template Expected<unsigned __int128, ConversionCode>
1118 str_to_integral<unsigned __int128>(StringPiece* src) noexcept;
1119 #endif
1120
1121 template <typename T>
1122 typename std::
1123     enable_if<std::is_same<T, bool>::value, Expected<T, ConversionCode>>::type
1124     convertTo(StringPiece* src) noexcept {
1125   return str_to_bool(src);
1126 }
1127
1128 template <typename T>
1129 typename std::enable_if<
1130     std::is_floating_point<T>::value,
1131     Expected<T, ConversionCode>>::type
1132 convertTo(StringPiece* src) noexcept {
1133   return str_to_floating<T>(src);
1134 }
1135
1136 template <typename T>
1137 typename std::enable_if<
1138     std::is_integral<T>::value && !std::is_same<T, bool>::value,
1139     Expected<T, ConversionCode>>::type
1140 convertTo(StringPiece* src) noexcept {
1141   return str_to_integral<T>(src);
1142 }
1143
1144 } // namespace detail
1145
1146 /**
1147  * String represented as a pair of pointers to char to unsigned
1148  * integrals. Assumes NO whitespace before or after.
1149  */
1150 template <typename Tgt>
1151 typename std::enable_if<
1152     std::is_integral<Tgt>::value && !std::is_same<Tgt, bool>::value,
1153     Expected<Tgt, ConversionCode>>::type
1154 tryTo(const char* b, const char* e) {
1155   return detail::digits_to<Tgt>(b, e);
1156 }
1157
1158 template <typename Tgt>
1159 typename std::enable_if<
1160     std::is_integral<Tgt>::value && !std::is_same<Tgt, bool>::value,
1161     Tgt>::type
1162 to(const char* b, const char* e) {
1163   return tryTo<Tgt>(b, e).thenOrThrow(
1164       [](Tgt res) { return res; },
1165       [=](ConversionCode code) {
1166         return makeConversionError(code, StringPiece(b, e));
1167       });
1168 }
1169
1170 /*******************************************************************************
1171  * Conversions from string types to arithmetic types.
1172  ******************************************************************************/
1173
1174 /**
1175  * Parsing strings to numeric types.
1176  */
1177 template <typename Tgt>
1178 FOLLY_NODISCARD inline typename std::enable_if<
1179     std::is_arithmetic<Tgt>::value,
1180     Expected<StringPiece, ConversionCode>>::type
1181 parseTo(StringPiece src, Tgt& out) {
1182   return detail::convertTo<Tgt>(&src).then(
1183       [&](Tgt res) { return void(out = res), src; });
1184 }
1185
1186 /*******************************************************************************
1187  * Integral / Floating Point to integral / Floating Point
1188  ******************************************************************************/
1189
1190 namespace detail {
1191
1192 /**
1193  * Bool to integral/float doesn't need any special checks, and this
1194  * overload means we aren't trying to see if a bool is less than
1195  * an integer.
1196  */
1197 template <class Tgt>
1198 typename std::enable_if<
1199     !std::is_same<Tgt, bool>::value &&
1200         (std::is_integral<Tgt>::value || std::is_floating_point<Tgt>::value),
1201     Expected<Tgt, ConversionCode>>::type
1202 convertTo(const bool& value) noexcept {
1203   return static_cast<Tgt>(value ? 1 : 0);
1204 }
1205
1206 /**
1207  * Checked conversion from integral to integral. The checks are only
1208  * performed when meaningful, e.g. conversion from int to long goes
1209  * unchecked.
1210  */
1211 template <class Tgt, class Src>
1212 typename std::enable_if<
1213     std::is_integral<Src>::value && !std::is_same<Tgt, Src>::value &&
1214         !std::is_same<Tgt, bool>::value &&
1215         std::is_integral<Tgt>::value,
1216     Expected<Tgt, ConversionCode>>::type
1217 convertTo(const Src& value) noexcept {
1218   /* static */ if (
1219       folly::_t<std::make_unsigned<Tgt>>(std::numeric_limits<Tgt>::max()) <
1220       folly::_t<std::make_unsigned<Src>>(std::numeric_limits<Src>::max())) {
1221     if (greater_than<Tgt, std::numeric_limits<Tgt>::max()>(value)) {
1222       return makeUnexpected(ConversionCode::ARITH_POSITIVE_OVERFLOW);
1223     }
1224   }
1225   /* static */ if (
1226       std::is_signed<Src>::value &&
1227       (!std::is_signed<Tgt>::value || sizeof(Src) > sizeof(Tgt))) {
1228     if (less_than<Tgt, std::numeric_limits<Tgt>::min()>(value)) {
1229       return makeUnexpected(ConversionCode::ARITH_NEGATIVE_OVERFLOW);
1230     }
1231   }
1232   return static_cast<Tgt>(value);
1233 }
1234
1235 /**
1236  * Checked conversion from floating to floating. The checks are only
1237  * performed when meaningful, e.g. conversion from float to double goes
1238  * unchecked.
1239  */
1240 template <class Tgt, class Src>
1241 typename std::enable_if<
1242     std::is_floating_point<Tgt>::value && std::is_floating_point<Src>::value &&
1243         !std::is_same<Tgt, Src>::value,
1244     Expected<Tgt, ConversionCode>>::type
1245 convertTo(const Src& value) noexcept {
1246   /* static */ if (
1247       std::numeric_limits<Tgt>::max() < std::numeric_limits<Src>::max()) {
1248     if (value > std::numeric_limits<Tgt>::max()) {
1249       return makeUnexpected(ConversionCode::ARITH_POSITIVE_OVERFLOW);
1250     }
1251     if (value < std::numeric_limits<Tgt>::lowest()) {
1252       return makeUnexpected(ConversionCode::ARITH_NEGATIVE_OVERFLOW);
1253     }
1254   }
1255   return static_cast<Tgt>(value);
1256 }
1257
1258 /**
1259  * Check if a floating point value can safely be converted to an
1260  * integer value without triggering undefined behaviour.
1261  */
1262 template <typename Tgt, typename Src>
1263 inline typename std::enable_if<
1264     std::is_floating_point<Src>::value && std::is_integral<Tgt>::value &&
1265         !std::is_same<Tgt, bool>::value,
1266     bool>::type
1267 checkConversion(const Src& value) {
1268   constexpr Src tgtMaxAsSrc = static_cast<Src>(std::numeric_limits<Tgt>::max());
1269   constexpr Src tgtMinAsSrc = static_cast<Src>(std::numeric_limits<Tgt>::min());
1270   if (value >= tgtMaxAsSrc) {
1271     if (value > tgtMaxAsSrc) {
1272       return false;
1273     }
1274     const Src mmax = folly::nextafter(tgtMaxAsSrc, Src());
1275     if (static_cast<Tgt>(value - mmax) >
1276         std::numeric_limits<Tgt>::max() - static_cast<Tgt>(mmax)) {
1277       return false;
1278     }
1279   } else if (std::is_signed<Tgt>::value && value <= tgtMinAsSrc) {
1280     if (value < tgtMinAsSrc) {
1281       return false;
1282     }
1283     const Src mmin = folly::nextafter(tgtMinAsSrc, Src());
1284     if (static_cast<Tgt>(value - mmin) <
1285         std::numeric_limits<Tgt>::min() - static_cast<Tgt>(mmin)) {
1286       return false;
1287     }
1288   }
1289   return true;
1290 }
1291
1292 // Integers can always safely be converted to floating point values
1293 template <typename Tgt, typename Src>
1294 constexpr typename std::enable_if<
1295     std::is_integral<Src>::value && std::is_floating_point<Tgt>::value,
1296     bool>::type
1297 checkConversion(const Src&) {
1298   return true;
1299 }
1300
1301 // Also, floating point values can always be safely converted to bool
1302 // Per the standard, any floating point value that is not zero will yield true
1303 template <typename Tgt, typename Src>
1304 constexpr typename std::enable_if<
1305     std::is_floating_point<Src>::value && std::is_same<Tgt, bool>::value,
1306     bool>::type
1307 checkConversion(const Src&) {
1308   return true;
1309 }
1310
1311 /**
1312  * Checked conversion from integral to floating point and back. The
1313  * result must be convertible back to the source type without loss of
1314  * precision. This seems Draconian but sometimes is what's needed, and
1315  * complements existing routines nicely. For various rounding
1316  * routines, see <math>.
1317  */
1318 template <typename Tgt, typename Src>
1319 typename std::enable_if<
1320     (std::is_integral<Src>::value && std::is_floating_point<Tgt>::value) ||
1321         (std::is_floating_point<Src>::value && std::is_integral<Tgt>::value),
1322     Expected<Tgt, ConversionCode>>::type
1323 convertTo(const Src& value) noexcept {
1324   if (LIKELY(checkConversion<Tgt>(value))) {
1325     Tgt result = static_cast<Tgt>(value);
1326     if (LIKELY(checkConversion<Src>(result))) {
1327       Src witness = static_cast<Src>(result);
1328       if (LIKELY(value == witness)) {
1329         return result;
1330       }
1331     }
1332   }
1333   return makeUnexpected(ConversionCode::ARITH_LOSS_OF_PRECISION);
1334 }
1335
1336 template <typename Tgt, typename Src>
1337 inline std::string errorValue(const Src& value) {
1338 #ifdef FOLLY_HAS_RTTI
1339   return to<std::string>("(", demangle(typeid(Tgt)), ") ", value);
1340 #else
1341   return to<std::string>(value);
1342 #endif
1343 }
1344
1345 template <typename Tgt, typename Src>
1346 using IsArithToArith = std::integral_constant<
1347     bool,
1348     !std::is_same<Tgt, Src>::value && !std::is_same<Tgt, bool>::value &&
1349         std::is_arithmetic<Src>::value &&
1350         std::is_arithmetic<Tgt>::value>;
1351
1352 } // namespace detail
1353
1354 template <typename Tgt, typename Src>
1355 typename std::enable_if<
1356     detail::IsArithToArith<Tgt, Src>::value,
1357     Expected<Tgt, ConversionCode>>::type
1358 tryTo(const Src& value) noexcept {
1359   return detail::convertTo<Tgt>(value);
1360 }
1361
1362 template <typename Tgt, typename Src>
1363 typename std::enable_if<detail::IsArithToArith<Tgt, Src>::value, Tgt>::type to(
1364     const Src& value) {
1365   return tryTo<Tgt>(value).thenOrThrow(
1366       [](Tgt res) { return res; },
1367       [&](ConversionCode e) {
1368         return makeConversionError(e, detail::errorValue<Tgt>(value));
1369       });
1370 }
1371
1372 /*******************************************************************************
1373  * Custom Conversions
1374  *
1375  * Any type can be used with folly::to by implementing parseTo. The
1376  * implementation should be provided in the namespace of the type to facilitate
1377  * argument-dependent lookup:
1378  *
1379  * namespace other_namespace {
1380  * ::folly::Expected<::folly::StringPiece, SomeErrorCode>
1381  *   parseTo(::folly::StringPiece, OtherType&) noexcept;
1382  * }
1383  ******************************************************************************/
1384 template <class T>
1385 FOLLY_NODISCARD typename std::enable_if<
1386     std::is_enum<T>::value,
1387     Expected<StringPiece, ConversionCode>>::type
1388 parseTo(StringPiece in, T& out) noexcept {
1389   typename std::underlying_type<T>::type tmp{};
1390   auto restOrError = parseTo(in, tmp);
1391   out = static_cast<T>(tmp); // Harmless if parseTo fails
1392   return restOrError;
1393 }
1394
1395 FOLLY_NODISCARD
1396 inline Expected<StringPiece, ConversionCode> parseTo(
1397     StringPiece in,
1398     StringPiece& out) noexcept {
1399   out = in;
1400   return StringPiece{in.end(), in.end()};
1401 }
1402
1403 FOLLY_NODISCARD
1404 inline Expected<StringPiece, ConversionCode> parseTo(
1405     StringPiece in,
1406     std::string& out) {
1407   out.clear();
1408   out.append(in.data(), in.size()); // TODO try/catch?
1409   return StringPiece{in.end(), in.end()};
1410 }
1411
1412 FOLLY_NODISCARD
1413 inline Expected<StringPiece, ConversionCode> parseTo(
1414     StringPiece in,
1415     fbstring& out) {
1416   out.clear();
1417   out.append(in.data(), in.size()); // TODO try/catch?
1418   return StringPiece{in.end(), in.end()};
1419 }
1420
1421 namespace detail {
1422 template <typename Tgt>
1423 using ParseToResult = decltype(parseTo(StringPiece{}, std::declval<Tgt&>()));
1424
1425 struct CheckTrailingSpace {
1426   Expected<Unit, ConversionCode> operator()(StringPiece sp) const {
1427     auto e = enforceWhitespaceErr(sp);
1428     if (UNLIKELY(e != ConversionCode::SUCCESS)) {
1429       return makeUnexpected(e);
1430     }
1431     return unit;
1432   }
1433 };
1434
1435 template <class Error>
1436 struct ReturnUnit {
1437   template <class T>
1438   constexpr Expected<Unit, Error> operator()(T&&) const {
1439     return unit;
1440   }
1441 };
1442
1443 // Older versions of the parseTo customization point threw on error and
1444 // returned void. Handle that.
1445 template <class Tgt>
1446 inline typename std::enable_if<
1447     std::is_void<ParseToResult<Tgt>>::value,
1448     Expected<StringPiece, ConversionCode>>::type
1449 parseToWrap(StringPiece sp, Tgt& out) {
1450   parseTo(sp, out);
1451   return StringPiece(sp.end(), sp.end());
1452 }
1453
1454 template <class Tgt>
1455 inline typename std::enable_if<
1456     !std::is_void<ParseToResult<Tgt>>::value,
1457     ParseToResult<Tgt>>::type
1458 parseToWrap(StringPiece sp, Tgt& out) {
1459   return parseTo(sp, out);
1460 }
1461
1462 template <typename Tgt>
1463 using ParseToError = ExpectedErrorType<decltype(
1464     detail::parseToWrap(StringPiece{}, std::declval<Tgt&>()))>;
1465
1466 } // namespace detail
1467
1468 /**
1469  * String or StringPiece to target conversion. Accepts leading and trailing
1470  * whitespace, but no non-space trailing characters.
1471  */
1472
1473 template <class Tgt>
1474 inline typename std::enable_if<
1475     !std::is_same<StringPiece, Tgt>::value,
1476     Expected<Tgt, detail::ParseToError<Tgt>>>::type
1477 tryTo(StringPiece src) {
1478   Tgt result{};
1479   using Error = detail::ParseToError<Tgt>;
1480   using Check = typename std::conditional<
1481       std::is_arithmetic<Tgt>::value,
1482       detail::CheckTrailingSpace,
1483       detail::ReturnUnit<Error>>::type;
1484   return parseTo(src, result).then(Check(), [&](Unit) {
1485     return std::move(result);
1486   });
1487 }
1488
1489 template <class Tgt, class Src>
1490 inline typename std::enable_if<
1491     IsSomeString<Src>::value && !std::is_same<StringPiece, Tgt>::value,
1492     Tgt>::type
1493 to(Src const& src) {
1494   return to<Tgt>(StringPiece(src.data(), src.size()));
1495 }
1496
1497 template <class Tgt>
1498 inline
1499     typename std::enable_if<!std::is_same<StringPiece, Tgt>::value, Tgt>::type
1500     to(StringPiece src) {
1501   Tgt result{};
1502   using Error = detail::ParseToError<Tgt>;
1503   using Check = typename std::conditional<
1504       std::is_arithmetic<Tgt>::value,
1505       detail::CheckTrailingSpace,
1506       detail::ReturnUnit<Error>>::type;
1507   auto tmp = detail::parseToWrap(src, result);
1508   return tmp
1509       .thenOrThrow(Check(), [&](Error e) { throw makeConversionError(e, src); })
1510       .thenOrThrow(
1511           [&](Unit) { return std::move(result); },
1512           [&](Error e) { throw makeConversionError(e, tmp.value()); });
1513 }
1514
1515 /**
1516  * tryTo/to that take the strings by pointer so the caller gets information
1517  * about how much of the string was consumed by the conversion. These do not
1518  * check for trailing whitepsace.
1519  */
1520 template <class Tgt>
1521 Expected<Tgt, detail::ParseToError<Tgt>> tryTo(StringPiece* src) {
1522   Tgt result;
1523   return parseTo(*src, result).then([&, src](StringPiece sp) -> Tgt {
1524     *src = sp;
1525     return std::move(result);
1526   });
1527 }
1528
1529 template <class Tgt>
1530 Tgt to(StringPiece* src) {
1531   Tgt result{};
1532   using Error = detail::ParseToError<Tgt>;
1533   return parseTo(*src, result)
1534       .thenOrThrow(
1535           [&, src](StringPiece sp) -> Tgt {
1536             *src = sp;
1537             return std::move(result);
1538           },
1539           [=](Error e) { return makeConversionError(e, *src); });
1540 }
1541
1542 /*******************************************************************************
1543  * Enum to anything and back
1544  ******************************************************************************/
1545
1546 template <class Tgt, class Src>
1547 typename std::enable_if<
1548     std::is_enum<Src>::value && !std::is_same<Src, Tgt>::value &&
1549         !std::is_convertible<Tgt, StringPiece>::value,
1550     Expected<Tgt, ConversionCode>>::type
1551 tryTo(const Src& value) {
1552   using I = typename std::underlying_type<Src>::type;
1553   return tryTo<Tgt>(static_cast<I>(value));
1554 }
1555
1556 template <class Tgt, class Src>
1557 typename std::enable_if<
1558     !std::is_convertible<Src, StringPiece>::valuea &&
1559         std::is_enum<Tgt>::value && !std::is_same<Src, Tgt>::value,
1560     Expected<Tgt, ConversionCode>>::type
1561 tryTo(const Src& value) {
1562   using I = typename std::underlying_type<Tgt>::type;
1563   return tryTo<I>(value).then([](I i) { return static_cast<Tgt>(i); });
1564 }
1565
1566 template <class Tgt, class Src>
1567 typename std::enable_if<
1568     std::is_enum<Src>::value && !std::is_same<Src, Tgt>::value &&
1569         !std::is_convertible<Tgt, StringPiece>::value,
1570     Tgt>::type
1571 to(const Src& value) {
1572   return to<Tgt>(static_cast<typename std::underlying_type<Src>::type>(value));
1573 }
1574
1575 template <class Tgt, class Src>
1576 typename std::enable_if<
1577     !std::is_convertible<Src, StringPiece>::value && std::is_enum<Tgt>::value &&
1578         !std::is_same<Src, Tgt>::value,
1579     Tgt>::type
1580 to(const Src& value) {
1581   return static_cast<Tgt>(to<typename std::underlying_type<Tgt>::type>(value));
1582 }
1583
1584 } // namespace folly