==> tests/rsfmt.c <==1/* Strings, durations and floats as Rust's format! writes them (expected
2 * strings are what rustc 1.88's format! prints for the same values). */
3#include "mesh/check.h"
4#include "mesh/rsfmt.h"
5
6#include <math.h>
7#include <stdlib.h>
8
9static mesh_buf b;
10static const char *s(void) { return mesh_buf_str(&b); }
11
12static void f32_is(float v, const char *want) {
13 mesh_buf_clear(&b);
14 mesh_rs_f32(&b, v);
15 CHECK_S(s(), want);
16}
17static void f64_is(double v, const char *want) {
18 mesh_buf_clear(&b);
19 mesh_rs_f64(&b, v);
20 CHECK_S(s(), want);
21}
22static void dur_is(uint64_t secs, uint32_t ns, const char *want) {
23 mesh_buf_clear(&b);
24 mesh_rs_duration(&b, secs, ns);
25 CHECK_S(s(), want);
26}
27
28int main(void) {
29 mesh_rs_debug_cstr(&b, "a\"b\\c\nd\te\x01" "f'g");
30 CHECK_S(s(), "\"a\\\"b\\\\c\\nd\\te\\u{1}f'g\"");
31 mesh_buf_clear(&b);
32 mesh_rs_debug_str(&b, "x\0y", 3);
33 CHECK_S(s(), "\"x\\0y\"");
34 mesh_buf_clear(&b);
35 mesh_rs_debug_cstr(&b, "caf\xc3\xa9");
36 CHECK_S(s(), "\"caf\xc3\xa9\"");
37
38 dur_is(10, 0, "10s");
39 dur_is(30, 0, "30s");
40 dur_is(1, 500000000, "1.5s");
41 dur_is(0, 500000000, "500ms");
42 dur_is(0, 2500000, "2.5ms");
43 dur_is(0, 40000, "40\xc2\xb5s");
44 dur_is(0, 7, "7ns");
45 dur_is(0, 0, "0ns");
46 dur_is(2, 1, "2.000000001s");
47 mesh_buf_clear(&b);
48 mesh_rs_duration_ms(&b, 120000);
49 CHECK_S(s(), "120s");
50
51 f32_is(0.48f, "0.48");
52 f32_is(1.0f, "1");
53 f32_is(0.1f, "0.1");
54 f32_is(1e20f, "100000000000000000000");
55 f32_is(1e-7f, "0.0000001");
56 f32_is(-2.5f, "-2.5");
57 f32_is(-0.0f, "-0");
58 f32_is(16777216.0f, "16777216");
59 f32_is(3.4028235e38f, "340282350000000000000000000000000000000");
60 f32_is(NAN, "NaN");
61 f32_is(-INFINITY, "-inf");
62 f64_is(0.1 + 0.2, "0.30000000000000004");
63 f64_is(1234.5, "1234.5");
64 {
65 /* 5e-324: "0." then 323 zeros then 5 (326 characters, as rustc prints it). */
66 char want[400] = "0.";
67 for (int i = 0; i < 323; i++) want[2 + i] = '0';
68 want[325] = '5';
69 want[326] = 0;
70 f64_is(5e-324, want);
71 }
72
73 mesh_buf_clear(&b);
74 mesh_rs_fixed(&b, 0.125, 2);
75 CHECK_S(s(), "0.12");
76 mesh_buf_clear(&b);
77 mesh_rs_fixed(&b, 2087.3, 0);
78 CHECK_S(s(), "2087");
79 mesh_buf_clear(&b);
80 mesh_rs_fixed(&b, 0.25, 1);
81 mesh_buf_putc(&b, ' ');
82 mesh_rs_fixed(&b, 0.35, 1);
83 mesh_buf_putc(&b, ' ');
84 mesh_rs_fixed(&b, 2.0005, 3);
85 CHECK_S(s(), "0.2 0.3 2.001");
86 mesh_buf_clear(&b);
87 mesh_rs_debug_cstr(&b, "caf\xc3\xa9\x7f");
88 CHECK_S(s(), "\"caf\xc3\xa9\\u{7f}\"");
89 /* from_utf8_lossy, as rustc 1.88 prints String::from_utf8_lossy of the same bytes. */
90 mesh_buf_clear(&b);
91 mesh_rs_lossy(&b, "a\xff" "b\xe2\x82" "c\xf0\x9f\x98\x80\xed\xa0\x80\xc3", 15);
92 CHECK_S(s(), "a\xef\xbf\xbd" "b\xef\xbf\xbd" "c\xf0\x9f\x98\x80\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd");
93 CHECK(mesh_rs_utf8_valid("caf\xc3\xa9", 5));
94 CHECK(!mesh_rs_utf8_valid("\xc3", 1));
95 /* str::parse: what Rust accepts and refuses. */
96 uint64_t u;
97 uint32_t u32;
98 int64_t i64;
99 CHECK_I(mesh_rs_parse_u64("", 0, &u), MESH_RS_EMPTY);
100 CHECK_I(mesh_rs_parse_u64("+", 1, &u), MESH_RS_INVALID);
101 CHECK_I(mesh_rs_parse_u64("+7", 2, &u), 0);
102 CHECK_U(u, 7);
103 CHECK_I(mesh_rs_parse_u64("-7", 2, &u), MESH_RS_INVALID);
104 CHECK_I(mesh_rs_parse_u64("18446744073709551615", 20, &u), 0);
105 CHECK_I(mesh_rs_parse_u64("18446744073709551616", 20, &u), MESH_RS_OVERFLOW);
106 CHECK_I(mesh_rs_parse_u64("1x", 2, &u), MESH_RS_INVALID);
107 CHECK_I(mesh_rs_parse_u32("4294967296", 10, &u32), MESH_RS_OVERFLOW);
108 CHECK_I(mesh_rs_parse_i64("-9223372036854775808", 20, &i64), 0);
109 CHECK(i64 == INT64_MIN);
110 CHECK_I(mesh_rs_parse_i64("9223372036854775808", 19, &i64), MESH_RS_OVERFLOW);
111 CHECK_S(mesh_rs_parse_error(MESH_RS_OVERFLOW), "number too large to fit in target type");
112 float fl;
113 double db;
114 CHECK_I(mesh_rs_parse_f32("1.79", 4, &fl), 0);
115 CHECK_F32_BITS(fl, 0x3fe51eb8u);
116 CHECK_I(mesh_rs_parse_f32(".5", 2, &fl), 0);
117 CHECK_I(mesh_rs_parse_f32("5.", 2, &fl), 0);
118 CHECK_I(mesh_rs_parse_f32("-1e5", 4, &fl), 0);
119 CHECK_I(mesh_rs_parse_f32("Infinity", 8, &fl), 0);
120 CHECK_I(mesh_rs_parse_f32("NaN", 3, &fl), 0);
121 CHECK_I(mesh_rs_parse_f32("0x10", 4, &fl), MESH_RS_FLOAT_INVALID);
122 CHECK_I(mesh_rs_parse_f32(" 1", 2, &fl), MESH_RS_FLOAT_INVALID);
123 CHECK_I(mesh_rs_parse_f32("1e", 2, &fl), MESH_RS_FLOAT_INVALID);
124 CHECK_I(mesh_rs_parse_f32(".", 1, &fl), MESH_RS_FLOAT_INVALID);
125 CHECK_I(mesh_rs_parse_f64("", 0, &db), MESH_RS_FLOAT_EMPTY);
126 CHECK_I(mesh_rs_parse_f64("2.5e-3", 6, &db), 0);
127 CHECK(db == 2.5e-3);
128 mesh_buf_free(&b);
129 return mesh_check_done();
130}