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