forked from feather-rs/feather
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommon.py
More file actions
164 lines (130 loc) · 4.92 KB
/
Copy pathcommon.py
File metadata and controls
164 lines (130 loc) · 4.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
"""Common code shared by most code generators."""
from subprocess import run
from json import load
from re import split
from pathlib import Path
from typing import List
LIBCRAFT_ROOT = Path(__file__).parents[1] / ".."
PRISMARINEJS_BASE_PATH = Path(__file__).parents[1] / ".." / ".." / "minecraft-data" / "data" / "pc"
LIBCRAFT_DATA_BASE_PATH = Path(__file__).parents[1] / "libcraft-data"
def rustfmt(file_path):
""" Runs rustfmt on a file"""
run(["rustfmt", file_path])
def load_minecraft_json(name: str, version="1.16.1") -> dict:
"""
Loads a JSON file from the minecraft-data sub repository.
Parameters:
name (str): Name of the file to load
version (str): String matching the targe minecraft version, defaults to 1.16.1
Returns:
A dict containing JSON content
"""
file = open(PRISMARINEJS_BASE_PATH / version / name)
return load(file)
def load_feather_json(name: str) -> dict:
"""
Loads a JSON file from the feather directory
Parameters:
name (str): Name of the file to load
Returns:
A dict containing JSON contents
"""
file = open(LIBCRAFT_DATA_BASE_PATH / name)
return load(file)
def output(path: str, content: str):
"""
Writes the contents to a file in provided path, then runs rustfmt.
Parameters:
path: Path to destination file, relative to libcraft root
content: Contents to be written in the file
"""
path = LIBCRAFT_ROOT / path
if not path.parent.exists():
return print(f"Couldn't write to file.\nPath {path.parent} does not exist")
f = open(path, "w")
f.write("// This file is @generated. Please do not edit.\n")
f.write(content)
f.close()
print(f"Generated {path.name}")
rustfmt(path)
def generate_enum_property(
enum: str, # Identifier of the enum (e.g. "Biome")
property_name: str, # Name of the property
type_: str, # The property type (e.g. u32, &str
mapping: dict, # Dictionary mapping from enum variant name => property value expression
# Whether to generate the reverse mapping (property value => Some(Self))
reverse=False,
return_type=None,
# Property type that should be returned. This is used when the type has a lifetime, such as &'static str
# Whether to bind enum fields using Enum::Variant { .. }
needs_bindings=False,
) -> str:
"""
Generates lookup functions for an enum.
Generates two function for an enum, one which maps the enum value to some
property value and one which does the reverse (returning an Option)
"""
if return_type is None:
return_type = type_
self_to_prop = ""
prop_to_self = ""
# Add quotes to strings
if type_ == "&str":
for key, property_value in mapping.items():
mapping[key] = f'"{property_value}"'
# If floats are needed, convert integers to floats
if type_ == "f32" or type_ == "f64":
for key, property_value in mapping.items():
mapping[key] = f'{property_value} as {type_}'
# Bools are lowercase in Rust
if type_ == "bool":
for key, property_value in mapping.items():
mapping[key] = str(property_value).lower()
for variant, property_value in mapping.items():
fields = ""
if needs_bindings:
fields = "{ .. }"
self_to_prop += f"{enum}::{variant} {fields} => {{ {property_value} }},"
prop_to_self += f"{property_value} => Some({enum}::{variant}),"
result = f"""
#[allow(warnings)]
#[allow(clippy::all)]
impl {enum} {{
/// Returns the `{property_name}` property of this `{enum}`.
pub fn {property_name}(&self) -> {return_type} {{
match self {{
{self_to_prop}
}}
}}
"""
if reverse:
result += f"""
/// Gets a `{enum}` by its `{property_name}`.
pub fn from_{property_name}({property_name}: {type_}) -> Option<Self> {{
match {property_name} {{
{prop_to_self}
_ => None,
}}
}}
"""
# closing brace
result += "}"
return result
def generate_enum(name: str, variants: List[str], derives: List[str] = [], prelude: str = "") -> str:
"""Generates an enum definition with the provided variants and extra derives."""
body = ','.join(variants) + ','
extra_derives = "" if len(derives) == 0 else ',' + ','.join(derives)
output = f"""
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord{extra_derives})]"""
if len(prelude) != 0:
output += f"""
{prelude}"""
output += f"""
pub enum {name} {{
{body}
}}
"""
return output
def camel_case(string: str) -> str:
"""Converts a string to UpperCamelCase."""
return ''.join(a.capitalize() for a in split('([^a-zA-Z0-9])', string) if a.isalnum())