Skip to main content

yog_data/export/
mod.rs

1//! The binary form's constants for the other languages' readers — the
2//! IDE's TypeScript (`yog-data-export`), so the tags are written once.
3
4mod types;
5
6use crate::binary::{self, tag};
7use crate::{Diagnostic, Schema, Seg, Severity};
8use yog_codegen::{Header, Literals, Regenerate};
9use yog_codegen_typescript::TypeScript;
10
11const HEADER: Header = Header {
12    tool: "yog-data",
13    source: "Yog-Mod-Loader/rust/crates/yog-data",
14    regenerate: Regenerate::Command("cargo run -p yog-data --bin yog-data-export"),
15};
16
17/// A TypeScript module: the header, the tags, the strings' and frames' rules.
18pub fn typescript() -> String {
19    let magic = String::from_utf8_lossy(binary::MAGIC);
20    let mut out = format!(
21        "{}\n\
22         /** What Yog Data starts with, and its version. */\n\
23         export const MAGIC = {};\n\
24         export const VERSION = {};\n\
25         /** Nested deeper than this is malformed. */\n\
26         export const MAX_DEPTH = {};\n\
27         /** A string's varint is odd for a new string (its length), even for one already read (its index). */\n\
28         export const NEW_STRING = {};\n\
29         /** A stream's length: this many bytes, little-endian. */\n\
30         export const STREAM_LEN_BYTES = {};\n\
31         /** A frame's length (`yog_data::io`): this many bytes, little-endian; and the longest frame. */\n\
32         export const FRAME_LEN_BYTES = {};\n\
33         export const MAX_FRAME = {};\n\
34         /** A result's two sides: `{{ ok }}` or `{{ err }}`. */\n\
35         export const RESULT_OK = {};\n\
36         export const RESULT_ERR = {};\n\
37         \n/** A value's first byte: what it is. */\nexport const tag = {{\n",
38        HEADER.comment::<TypeScript>(),
39        TypeScript::string(&magic),
40        binary::VERSION,
41        binary::MAX_DEPTH,
42        binary::NEW_STRING,
43        binary::STREAM_LEN_BYTES,
44        size_of::<crate::io::Len>(),
45        crate::io::MAX_FRAME,
46        TypeScript::string(substrate_data::schema::RESULT_OK),
47        TypeScript::string(substrate_data::schema::RESULT_ERR),
48    );
49    for (name, value) in tag::ALL {
50        out.push_str(&format!("  {name}: {value},\n"));
51    }
52    out.push_str("} as const;\n");
53    out.push_str(&problems());
54    // The records every tool writes.
55    let shapes = [Severity::shape(), Seg::shape(), Diagnostic::shape()];
56    out.push('\n');
57    out.push_str(&types::declarations(&shapes));
58    out
59}
60
61/// Substrate Data's problem codes, by name (`NOT_A_REFERENCE: "SD0003"`).
62fn problems() -> String {
63    let mut out = String::from(
64        "\n/** What's wrong with data: Substrate Data's codes. */\nexport const dataProblem = {\n",
65    );
66    for p in crate::Problem::ALL {
67        out.push_str(&format!(
68            "  {}: {},\n",
69            constant_name(&format!("{p:?}")),
70            TypeScript::string(p.code())
71        ));
72    }
73    out.push_str("} as const;\n");
74    out
75}
76
77/// `NotAReference` → `NOT_A_REFERENCE`.
78fn constant_name(name: &str) -> String {
79    let mut out = String::new();
80    for (i, c) in name.chars().enumerate() {
81        if c.is_ascii_uppercase() && i > 0 {
82            out.push('_');
83        }
84        out.push(c.to_ascii_uppercase());
85    }
86    out
87}