skip to content
==> 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}