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