bitcoin_string/
strencodings.rs

1/*!
2  | Utilities for converting data from/to
3  | strings.
4  |
5  */
6
7crate::ix!();
8
9pub trait ToUpper {
10    fn to_upper(&self) -> Self;
11}
12
13pub trait ToLower {
14    fn to_lower(&self) -> Self;
15}
16
17//-------------------------------------------[.cpp/bitcoin/src/util/strencodings.h]
18
19/**
20  | Used by SanitizeString()
21  |
22  */
23pub enum SafeChars
24{
25    /**
26      | The full set of allowed chars
27      |
28      */
29    SAFE_CHARS_DEFAULT, 
30
31    /**
32      | BIP-0014 subset
33      |
34      */
35    SAFE_CHARS_UA_COMMENT, 
36
37    /**
38      | Chars allowed in filenames
39      |
40      */
41    SAFE_CHARS_FILENAME, 
42
43    /**
44      | Chars allowed in URIs (RFC 3986)
45      |
46      */
47    SAFE_CHARS_URI, 
48}
49
50/**
51  | LocaleIndependentAtoi is provided for backwards
52  | compatibility reasons.
53  |
54  | New code should use ToIntegral or the ParseInt*
55  | functions which provide parse error feedback.
56  |
57  | The goal of LocaleIndependentAtoi is to
58  | replicate the exact defined behaviour of atoi
59  | and atoi64 as they behave under the "C" locale.
60  */
61pub fn locale_independent_atoi<T>(str_: &str) -> T {
62
63    todo!();
64        /*
65            const_assert(std::is_integral<T>::value);
66        T result;
67        // Emulate atoi(...) handling of white space and leading +/-.
68        std::string s = TrimString(str);
69        if (!s.empty() && s[0] == '+') {
70            if (s.length() >= 2 && s[1] == '-') {
71                return 0;
72            }
73            s = s.substr(1);
74        }
75        auto [_, error_condition] = std::from_chars(s.data(), s.data() + s.size(), result);
76        if (error_condition != std::errc{}) {
77            return 0;
78        }
79        return result;
80        */
81}
82
83/**
84  | Tests if the given character is a decimal
85  | digit.
86  | 
87  | -----------
88  | @param[in] c
89  | 
90  | character to test
91  | 
92  | -----------
93  | @return
94  | 
95  | true if the argument is a decimal digit;
96  | otherwise false.
97  |
98  */
99pub fn is_digit(c: u8) -> bool {
100    
101    todo!();
102        /*
103            return c >= '0' && c <= '9';
104        */
105}
106
107/**
108  | Tests if the given character is a whitespace
109  | character. The whitespace characters
110  | are: 
111  |
112  | space, 
113  | form-feed ('\f'), 
114  | newline ('\n'), 
115  | carriage return ('\r'), 
116  | horizontal tab ('\t'), 
117  | and vertical tab ('\v').
118  | 
119  | This function is locale independent.
120  | Under the C locale this function gives
121  | the same result as std::isspace.
122  | 
123  | -----------
124  | @param[in] c
125  | 
126  | character to test
127  | 
128  | -----------
129  | @return
130  | 
131  | true if the argument is a whitespace
132  | character; otherwise false
133  |
134  */
135#[inline] pub fn is_space(c: u8) -> bool {
136    
137    todo!();
138        /*
139            return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v';
140        */
141}
142
143/**
144  | Convert string to integral type T. Leading
145  | whitespace, a leading +, or any trailing
146  | character fail the parsing.
147  | 
148  | The required format expressed as regex
149  | is `-?[0-9]+`. The minus sign is only
150  | permitted for signed integer types.
151  | 
152  | -----------
153  | @return
154  | 
155  | std::nullopt if the entire string could
156  | not be parsed, or if the parsed value
157  | is not in the range representable by
158  | the type T.
159  |
160  */
161pub fn to_integral<T>(str_: &str) -> Option<T> {
162
163    todo!();
164        /*
165            const_assert(std::is_integral<T>::value);
166        T result;
167        const auto [first_nonmatching, error_condition] = std::from_chars(str.data(), str.data() + str.size(), result);
168        if (first_nonmatching != str.data() + str.size() || error_condition != std::errc{}) {
169            return std::nullopt;
170        }
171        return result;
172        */
173}
174
175/**
176  | Timing-attack-resistant comparison.
177  | 
178  | Takes time proportional to length of
179  | first argument.
180  |
181  */
182pub fn timing_resistant_equal<T>(a: &T, b: &T) -> bool {
183
184    todo!();
185        /*
186            if (b.size() == 0) return a.size() == 0;
187        size_t accumulator = a.size() ^ b.size();
188        for (size_t i = 0; i < a.size(); i++)
189            accumulator |= a[i] ^ b[i%b.size()];
190        return accumulator == 0;
191        */
192}
193
194/**
195  | Convert from one power-of-2 number
196  | base to another.
197  |
198  */
199pub fn convert_bits<O, I, const frombits: i32, const tobits: i32, const pad: bool>(
200        outfn: &O,
201        it:    I,
202        end:   I) -> bool {
203
204    todo!();
205        /*
206            size_t acc = 0;
207        size_t bits = 0;
208        constexpr size_t maxv = (1 << tobits) - 1;
209        constexpr size_t max_acc = (1 << (frombits + tobits - 1)) - 1;
210        while (it != end) {
211            acc = ((acc << frombits) | *it) & max_acc;
212            bits += frombits;
213            while (bits >= tobits) {
214                bits -= tobits;
215                outfn((acc >> bits) & maxv);
216            }
217            ++it;
218        }
219        if (pad) {
220            if (bits) outfn((acc << (tobits - bits)) & maxv);
221        } else if (bits >= frombits || ((acc << (tobits - bits)) & maxv)) {
222            return false;
223        }
224        return true;
225        */
226}
227
228impl ToLower for u8 {
229
230    /**
231      | Converts the given character to its
232      | lowercase equivalent.
233      | 
234      | This function is locale independent.
235      | It only converts uppercase characters
236      | in the standard 7-bit ASCII range.
237      | 
238      | This is a feature, not a limitation.
239      | 
240      | -----------
241      | @param[in] c
242      | 
243      | the character to convert to lowercase.
244      | 
245      | -----------
246      | @return
247      | 
248      | the lowercase equivalent of c; or the
249      | argument if no conversion is possible.
250      |
251      */
252    fn to_lower(&self) -> u8 {
253
254        todo!();
255        /*
256                return (c >= 'A' && c <= 'Z' ? (c - 'A') + 'a' : c);
257            */
258    }
259}
260
261/**
262  | Converts the given character to its
263  | uppercase equivalent.
264  | 
265  | This function is locale independent.
266  | It only converts lowercase characters
267  | in the standard 7-bit ASCII range.
268  | 
269  | This is a feature, not a limitation.
270  | 
271  | -----------
272  | @param[in] c
273  | 
274  | the character to convert to uppercase.
275  | 
276  | -----------
277  | @return
278  | 
279  | the uppercase equivalent of c; or the
280  | argument if no conversion is possible.
281  |
282  */
283impl ToUpper for u8 {
284
285    fn to_upper(&self) -> u8 {
286        
287        todo!();
288            /*
289                return (c >= 'a' && c <= 'z' ? (c - 'a') + 'A' : c);
290            */
291    }
292}
293
294//-------------------------------------------[.cpp/bitcoin/src/util/strencodings.cpp]
295
296pub const CHARS_ALPHA_NUM: &'static str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
297
298lazy_static!{
299    static ref SAFE_CHARS: Box<[String]> = 
300        Box::new([
301            CHARS_ALPHA_NUM.to_owned() + " .,;-_/:?@()",            // SAFE_CHARS_DEFAULT
302            CHARS_ALPHA_NUM.to_owned() + " .,;-_?@",                // SAFE_CHARS_UA_COMMENT
303            CHARS_ALPHA_NUM.to_owned() + ".-_",                     // SAFE_CHARS_FILENAME
304            CHARS_ALPHA_NUM.to_owned() + "!*'();:@&=+$,/?#[]-_.~%", // SAFE_CHARS_URI
305        ]);
306}
307
308/**
309  | Remove unsafe chars. Safe chars chosen
310  | to allow simple messages/URLs/email
311  | addresses, but avoid anything even
312  | possibly remotely dangerous like &
313  | or >
314  | 
315  | -----------
316  | @param[in] str
317  | 
318  | The string to sanitize
319  | ----------
320  | @param[in] rule
321  | 
322  | The set of safe chars to choose (default:
323  | least restrictive)
324  | 
325  | -----------
326  | @return
327  | 
328  | A new string without unsafe chars
329  |
330  */
331pub fn sanitize_string(
332        str_: &str,
333        rule: Option<i32>) -> String {
334
335    let rule: i32 = rule.unwrap_or(SafeChars::SAFE_CHARS_DEFAULT as i32);
336    
337    todo!();
338        /*
339            std::string strResult;
340        for (std::string::size_type i = 0; i < str.size(); i++)
341        {
342            if (SAFE_CHARS[rule].find(str[i]) != std::string::npos)
343                strResult.push_back(str[i]);
344        }
345        return strResult;
346        */
347}
348
349pub const util_hexdigit: [i8; 256] = [ 
350    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
351    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
352    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
353    0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
354    -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
355    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
356    -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
357    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
358    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
359    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
360    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
361    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
362    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
363    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
364    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
365    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 
366];
367
368pub fn hex_digit(c: u8) -> i8 {
369    
370    todo!();
371        /*
372            return p_util_hexdigit[(unsigned char)c];
373        */
374}
375
376/**
377  | Returns true if each character in str
378  | is a hex character, and has an even number
379  | of hex digits.
380  |
381  */
382pub fn is_hex(str_: &str) -> bool {
383    
384    todo!();
385        /*
386            for(std::string::const_iterator it(str.begin()); it != str.end(); ++it)
387        {
388            if (HexDigit(*it) < 0)
389                return false;
390        }
391        return (str.size() > 0) && (str.size()%2 == 0);
392        */
393}
394
395/**
396  | Return true if the string is a hex number,
397  | optionally prefixed with "0x"
398  |
399  */
400pub fn is_hex_number(str_: &str) -> bool {
401    
402    todo!();
403        /*
404            size_t starting_location = 0;
405        if (str.size() > 2 && *str.begin() == '0' && *(str.begin()+1) == 'x') {
406            starting_location = 2;
407        }
408        for (const char c : str.substr(starting_location)) {
409            if (HexDigit(c) < 0) return false;
410        }
411        // Return false for empty string or "0x".
412        return (str.size() > starting_location);
413        */
414}
415
416pub fn parse_hex(psz: &str) -> Vec<u8> {
417    
418    todo!();
419        /*
420            // convert hex dump to vector
421        std::vector<unsigned char> vch;
422        while (true)
423        {
424            while (IsSpace(*psz))
425                psz++;
426            signed char c = HexDigit(*psz++);
427            if (c == (signed char)-1)
428                break;
429            unsigned char n = (c << 4);
430            c = HexDigit(*psz++);
431            if (c == (signed char)-1)
432                break;
433            n |= c;
434            vch.push_back(n);
435        }
436        return vch;
437        */
438}
439
440pub fn encode_base64_bytes(input: &[u8]) -> String {
441    
442    todo!();
443        /*
444            static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
445
446        std::string str;
447        str.reserve(((input.size() + 2) / 3) * 4);
448        ConvertBits<8, 6, true>([&](int v) { str += pbase64[v]; }, input.begin(), input.end());
449        while (str.size() % 4) str += '=';
450        return str;
451        */
452}
453
454pub fn encode_base64(str_: &String) -> String {
455    
456    todo!();
457        /*
458            return EncodeBase64(MakeUCharSpan(str));
459        */
460}
461
462pub fn decode_base64_bytes(
463        p:          *const u8,
464        pf_invalid: Option<*mut bool>) -> Vec<u8> {
465    
466    todo!();
467        /*
468            static const int decode64_table[256] =
469        {
470            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
471            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
472            -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
473            -1, -1, -1, -1, -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
474            15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
475            29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
476            49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
477            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
478            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
479            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
480            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
481            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
482            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
483        };
484
485        const char* e = p;
486        std::vector<uint8_t> val;
487        val.reserve(strlen(p));
488        while (*p != 0) {
489            int x = decode64_table[(unsigned char)*p];
490            if (x == -1) break;
491            val.push_back(x);
492            ++p;
493        }
494
495        std::vector<unsigned char> ret;
496        ret.reserve((val.size() * 3) / 4);
497        bool valid = ConvertBits<6, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
498
499        const char* q = p;
500        while (valid && *p != 0) {
501            if (*p != '=') {
502                valid = false;
503                break;
504            }
505            ++p;
506        }
507        valid = valid && (p - e) % 4 == 0 && p - q < 4;
508        if (pf_invalid) *pf_invalid = !valid;
509
510        return ret;
511        */
512}
513
514pub fn decode_base64(
515        str_:       &str,
516        pf_invalid: Option<&mut bool>) -> String {
517    
518    todo!();
519        /*
520            if (!ValidAsCString(str)) {
521            if (pf_invalid) {
522                *pf_invalid = true;
523            }
524            return {};
525        }
526        std::vector<unsigned char> vchRet = DecodeBase64(str.c_str(), pf_invalid);
527        return std::string((const char*)vchRet.data(), vchRet.size());
528        */
529}
530
531/**
532  | Base32 encode.
533  | 
534  | If `pad` is true, then the output will
535  | be padded with '=' so that its length
536  | is a multiple of 8.
537  |
538  */
539pub fn encode_base32_bytes(
540        input: &[u8],
541        pad:   Option<bool>) -> String {
542    let pad: bool = pad.unwrap_or(true);
543    
544    todo!();
545        /*
546            static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567";
547
548        std::string str;
549        str.reserve(((input.size() + 4) / 5) * 8);
550        ConvertBits<8, 5, true>([&](int v) { str += pbase32[v]; }, input.begin(), input.end());
551        if (pad) {
552            while (str.size() % 8) {
553                str += '=';
554            }
555        }
556        return str;
557        */
558}
559
560/**
561  | Base32 encode.
562  | 
563  | If `pad` is true, then the output will
564  | be padded with '=' so that its length
565  | is a multiple of 8.
566  |
567  */
568pub fn encode_base32(
569        str_: &[u8],
570        pad:  Option<bool>) -> String {
571    let pad: bool = pad.unwrap_or(true);
572    
573    todo!();
574        /*
575            return EncodeBase32(MakeUCharSpan(str), pad);
576        */
577}
578
579pub fn decode_base32_bytes(
580        p:          *const u8,
581        pf_invalid: Option<*mut bool>) -> Vec<u8> {
582    
583    todo!();
584        /*
585            static const int decode32_table[256] =
586        {
587            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
588            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
589            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1,
590            -1, -1, -1, -1, -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
591            15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1,  0,  1,  2,
592             3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
593            23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
594            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
595            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
596            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
597            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
598            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
599            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
600        };
601
602        const char* e = p;
603        std::vector<uint8_t> val;
604        val.reserve(strlen(p));
605        while (*p != 0) {
606            int x = decode32_table[(unsigned char)*p];
607            if (x == -1) break;
608            val.push_back(x);
609            ++p;
610        }
611
612        std::vector<unsigned char> ret;
613        ret.reserve((val.size() * 5) / 8);
614        bool valid = ConvertBits<5, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
615
616        const char* q = p;
617        while (valid && *p != 0) {
618            if (*p != '=') {
619                valid = false;
620                break;
621            }
622            ++p;
623        }
624        valid = valid && (p - e) % 8 == 0 && p - q < 8;
625        if (pf_invalid) *pf_invalid = !valid;
626
627        return ret;
628        */
629}
630
631pub fn decode_base32(
632        str_:       &str,
633        pf_invalid: Option<*mut bool>) -> String {
634    
635    todo!();
636        /*
637            if (!ValidAsCString(str)) {
638            if (pf_invalid) {
639                *pf_invalid = true;
640            }
641            return {};
642        }
643        std::vector<unsigned char> vchRet = DecodeBase32(str.c_str(), pf_invalid);
644        return std::string((const char*)vchRet.data(), vchRet.size());
645        */
646}
647
648pub fn parse_integral<T>(
649        str_: &String,
650        out:  *mut T) -> bool {
651
652    todo!();
653        /*
654            const_assert(std::is_integral<T>::value);
655        // Replicate the exact behavior of strtol/strtoll/strtoul/strtoull when
656        // handling leading +/- for backwards compatibility.
657        if (str.length() >= 2 && str[0] == '+' && str[1] == '-') {
658            return false;
659        }
660        const std::optional<T> opt_int = ToIntegral<T>((!str.empty() && str[0] == '+') ? str.substr(1) : str);
661        if (!opt_int) {
662            return false;
663        }
664        if (out != nullptr) {
665            *out = *opt_int;
666        }
667        return true;
668        */
669}
670
671/**
672  | Convert string to signed 32-bit integer
673  | with strict parse error feedback.
674  | 
675  | 
676  | -----------
677  | @return
678  | 
679  | true if the entire string could be parsed
680  | as valid integer, false if not the entire
681  | string could be parsed or when overflow
682  | or underflow occurred.
683  |
684  */
685pub fn parse_int32(
686        str_: &String,
687        out:  *mut i32) -> bool {
688    
689    todo!();
690        /*
691            return ParseIntegral<int32_t>(str, out);
692        */
693}
694
695/**
696  | Convert string to signed 64-bit integer
697  | with strict parse error feedback.
698  | 
699  | -----------
700  | @return
701  | 
702  | true if the entire string could be parsed
703  | as valid integer, false if not the entire
704  | string could be parsed or when overflow
705  | or underflow occurred.
706  |
707  */
708pub fn parse_int64(
709        str_: &String,
710        out:  *mut i64) -> bool {
711    
712    todo!();
713        /*
714            return ParseIntegral<int64_t>(str, out);
715        */
716}
717
718/**
719  | Convert decimal string to unsigned
720  | 8-bit integer with strict parse error
721  | feedback.
722  | 
723  | -----------
724  | @return
725  | 
726  | true if the entire string could be parsed
727  | as valid integer, false if not the entire
728  | string could be parsed or when overflow
729  | or underflow occurred.
730  |
731  */
732pub fn parse_uint8(
733        str_: &str,
734        out:  *mut u8) -> bool {
735    
736    todo!();
737        /*
738            return ParseIntegral<uint8_t>(str, out);
739        */
740}
741
742/**
743  | Convert decimal string to unsigned
744  | 16-bit integer with strict parse error
745  | feedback.
746  | 
747  | -----------
748  | @return
749  | 
750  | true if the entire string could be parsed
751  | as valid integer, false if the entire
752  | string could not be parsed or if overflow
753  | or underflow occurred.
754  |
755  */
756pub fn parse_uint16(
757        str_: &str,
758        out:  *mut u16) -> bool {
759    
760    todo!();
761        /*
762            return ParseIntegral<uint16_t>(str, out);
763        */
764}
765
766/**
767  | Convert decimal string to unsigned
768  | 32-bit integer with strict parse error
769  | feedback.
770  | 
771  | -----------
772  | @return
773  | 
774  | true if the entire string could be parsed
775  | as valid integer, false if not the entire
776  | string could be parsed or when overflow
777  | or underflow occurred.
778  |
779  */
780pub fn parse_uint32(
781        str_: &str,
782        out:  *mut u32) -> bool {
783    
784    todo!();
785        /*
786            return ParseIntegral<uint32_t>(str, out);
787        */
788}
789
790/**
791  | Convert decimal string to unsigned
792  | 64-bit integer with strict parse error
793  | feedback.
794  | 
795  | 
796  | -----------
797  | @return
798  | 
799  | true if the entire string could be parsed
800  | as valid integer, false if not the entire
801  | string could be parsed or when overflow
802  | or underflow occurred.
803  |
804  */
805pub fn parse_uint64(
806        str_: &str,
807        out:  *mut u64) -> bool {
808    
809    todo!();
810        /*
811            return ParseIntegral<uint64_t>(str, out);
812        */
813}
814
815/** 
816 | Upper bound for mantissa.
817 |
818 | 10^18-1 is the largest arbitrary decimal that
819 | will fit in a signed 64-bit integer.
820 |
821 | Larger integers cannot consist of arbitrary
822 | combinations of 0-9:
823 |
824 |   999999999999999999  1^18-1
825 |  9223372036854775807  (1<<63)-1  (max int64_t)
826 |  9999999999999999999  1^19-1     (would overflow)
827 */
828pub const UPPER_BOUND: i64 = 1000000000000000000 - 1;
829
830/**
831  | Helper function for ParseFixedPoint
832  |
833  */
834#[inline] pub fn process_mantissa_digit(
835        ch:              u8,
836        mantissa:        &mut i64,
837        mantissa_tzeros: &mut i32) -> bool {
838    
839    todo!();
840        /*
841            if(ch == '0')
842            ++mantissa_tzeros;
843        else {
844            for (int i=0; i<=mantissa_tzeros; ++i) {
845                if (mantissa > (UPPER_BOUND / 10LL))
846                    return false; /* overflow */
847                mantissa *= 10;
848            }
849            mantissa += ch - '0';
850            mantissa_tzeros = 0;
851        }
852        return true;
853        */
854}
855
856/**
857  | Parse number as fixed point according
858  | to JSON number syntax.
859  | 
860  | See https://json.org/number.gif
861  | 
862  | -----------
863  | @note
864  | 
865  | The result must be in the range (-10^18,10^18),
866  | otherwise an overflow error will trigger.
867  | 
868  | -----------
869  | @return
870  | 
871  | true on success, false on error.
872  |
873  */
874pub fn parse_fixed_point(
875        val:        &str,
876        decimals:   i32,
877        amount_out: *mut i64) -> bool {
878    
879    todo!();
880        /*
881            int64_t mantissa = 0;
882        int64_t exponent = 0;
883        int mantissa_tzeros = 0;
884        bool mantissa_sign = false;
885        bool exponent_sign = false;
886        int ptr = 0;
887        int end = val.size();
888        int point_ofs = 0;
889
890        if (ptr < end && val[ptr] == '-') {
891            mantissa_sign = true;
892            ++ptr;
893        }
894        if (ptr < end)
895        {
896            if (val[ptr] == '0') {
897                /* pass single 0 */
898                ++ptr;
899            } else if (val[ptr] >= '1' && val[ptr] <= '9') {
900                while (ptr < end && IsDigit(val[ptr])) {
901                    if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
902                        return false; /* overflow */
903                    ++ptr;
904                }
905            } else return false; /* missing expected digit */
906        } else return false; /* empty string or loose '-' */
907        if (ptr < end && val[ptr] == '.')
908        {
909            ++ptr;
910            if (ptr < end && IsDigit(val[ptr]))
911            {
912                while (ptr < end && IsDigit(val[ptr])) {
913                    if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
914                        return false; /* overflow */
915                    ++ptr;
916                    ++point_ofs;
917                }
918            } else return false; /* missing expected digit */
919        }
920        if (ptr < end && (val[ptr] == 'e' || val[ptr] == 'E'))
921        {
922            ++ptr;
923            if (ptr < end && val[ptr] == '+')
924                ++ptr;
925            else if (ptr < end && val[ptr] == '-') {
926                exponent_sign = true;
927                ++ptr;
928            }
929            if (ptr < end && IsDigit(val[ptr])) {
930                while (ptr < end && IsDigit(val[ptr])) {
931                    if (exponent > (UPPER_BOUND / 10LL))
932                        return false; /* overflow */
933                    exponent = exponent * 10 + val[ptr] - '0';
934                    ++ptr;
935                }
936            } else return false; /* missing expected digit */
937        }
938        if (ptr != end)
939            return false; /* trailing garbage */
940
941        /* finalize exponent */
942        if (exponent_sign)
943            exponent = -exponent;
944        exponent = exponent - point_ofs + mantissa_tzeros;
945
946        /* finalize mantissa */
947        if (mantissa_sign)
948            mantissa = -mantissa;
949
950        /* convert to one 64-bit fixed-point value */
951        exponent += decimals;
952        if (exponent < 0)
953            return false; /* cannot represent values smaller than 10^-decimals */
954        if (exponent >= 18)
955            return false; /* cannot represent values larger than or equal to 10^(18-decimals) */
956
957        for (int i=0; i < exponent; ++i) {
958            if (mantissa > (UPPER_BOUND / 10LL) || mantissa < -(UPPER_BOUND / 10LL))
959                return false; /* overflow */
960            mantissa *= 10;
961        }
962        if (mantissa > UPPER_BOUND || mantissa < -UPPER_BOUND)
963            return false; /* overflow */
964
965        if (amount_out)
966            *amount_out = mantissa;
967
968        return true;
969        */
970}
971
972impl ToLower for String {
973
974    /**
975      | Returns the lowercase equivalent of
976      | the given string.
977      | 
978      | This function is locale independent.
979      | It only converts uppercase characters
980      | in the standard 7-bit ASCII range.
981      | 
982      | This is a feature, not a limitation.
983      | 
984      | -----------
985      | @param[in] str
986      | 
987      | the string to convert to lowercase.
988      | 
989      | -----------
990      | @return
991      | 
992      | lowercased equivalent of str
993      |
994      */
995    fn to_lower(&self) -> String {
996
997        todo!();
998            /*
999                std::string r;
1000            for (auto ch : str) r += ToLower((unsigned char)ch);
1001            return r;
1002            */
1003    }
1004}
1005
1006/**
1007  | Returns the uppercase equivalent of
1008  | the given string.
1009  | 
1010  | This function is locale independent.
1011  | It only converts lowercase characters
1012  | in the standard 7-bit ASCII range.
1013  | 
1014  | This is a feature, not a limitation.
1015  | 
1016  | -----------
1017  | @param[in] str
1018  | 
1019  | the string to convert to uppercase.
1020  | 
1021  | -----------
1022  | @return
1023  | 
1024  | UPPERCASED EQUIVALENT OF str
1025  |
1026  */
1027impl ToUpper for String {
1028    fn to_upper(&self) -> String {
1029        
1030        todo!();
1031            /*
1032                std::string r;
1033            for (auto ch : str) r += ToUpper((unsigned char)ch);
1034            return r;
1035            */
1036    }
1037}
1038
1039/**
1040  | Capitalizes the first character of
1041  | the given string.
1042  | 
1043  | This function is locale independent.
1044  | It only converts lowercase characters
1045  | in the standard 7-bit ASCII range.
1046  | 
1047  | This is a feature, not a limitation.
1048  | 
1049  | -----------
1050  | @param[in] str
1051  | 
1052  | the string to capitalize.
1053  | 
1054  | -----------
1055  | @return
1056  | 
1057  | string with the first letter capitalized.
1058  |
1059  */
1060pub fn capitalize(str_: &str) -> String {
1061    
1062    todo!();
1063        /*
1064            if (str.empty()) return str;
1065        str[0] = ToUpper(str.front());
1066        return str;
1067        */
1068}
1069
1070/**
1071  | Convert a span of bytes to a lower-case
1072  | hexadecimal string.
1073  |
1074  */
1075pub fn hex_str(s: &[u8]) -> String {
1076    
1077    todo!();
1078        /*
1079            std::string rv(s.size() * 2, '\0');
1080        static constexpr char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
1081                                             '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
1082        auto it = rv.begin();
1083        for (uint8_t v : s) {
1084            *it++ = hexmap[v >> 4];
1085            *it++ = hexmap[v & 15];
1086        }
1087        assert(it == rv.end());
1088        return rv;
1089        */
1090}