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