-- NOTE: This must be ran in Roblox Studio to get up-to-date font values local contents = "" contents ..= "\ntype FontData = (&'static str, FontWeight, FontStyle);\n" local ENUM_IMPLEMENTATION = [[ #[derive(Debug, Clone, Copy, PartialEq)] pub(crate) enum <<ENUM_NAME>> { <<ENUM_NAMES>> } impl <<ENUM_NAME>> { pub(crate) fn as_<<NUMBER_TYPE>>(&self) -> <<NUMBER_TYPE>> { match self { <<ENUM_TO_NUMBERS>> } } pub(crate) fn from_<<NUMBER_TYPE>>(n: <<NUMBER_TYPE>>) -> Option<Self> { match n { <<NUMBERS_TO_ENUM>> _ => None, } } } impl Default for <<ENUM_NAME>> { fn default() -> Self { Self::<<DEFAULT_NAME>> } } impl std::str::FromStr for <<ENUM_NAME>> { type Err = &'static str; fn from_str(s: &str) -> Result<Self, Self::Err> { match s { <<STRINGS_TO_ENUM>> _ => Err("Unknown <<ENUM_NAME>>"), } } } impl std::fmt::Display for <<ENUM_NAME>> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, "{}", match self { <<ENUM_TO_STRINGS>> } ) } } impl<'lua> FromLua<'lua> for <<ENUM_NAME>> { fn from_lua(lua_value: LuaValue<'lua>, _: &'lua Lua) -> LuaResult<Self> { let mut message = None; if let LuaValue::UserData(ud) = &lua_value { let value = ud.borrow::<EnumItem>()?; if value.parent.desc.name == "<<ENUM_NAME>>" { if let Ok(value) = <<ENUM_NAME>>::from_str(&value.name) { return Ok(value); } else { message = Some(format!( "Found unknown Enum.<<ENUM_NAME>> value '{}'", value.name )); } } else { message = Some(format!( "Expected Enum.<<ENUM_NAME>>, got Enum.{}", value.parent.desc.name )); } } Err(LuaError::FromLuaConversionError { from: lua_value.type_name(), to: "Enum.<<ENUM_NAME>>", message, }) } } impl<'lua> ToLua<'lua> for <<ENUM_NAME>> { fn to_lua(self, lua: &'lua Lua) -> LuaResult<LuaValue<'lua>> { match EnumItem::from_enum_name_and_name("<<ENUM_NAME>>", self.to_string()) { Some(enum_item) => Ok(LuaValue::UserData(lua.create_userdata(enum_item)?)), None => Err(LuaError::ToLuaConversionError { from: "<<ENUM_NAME>>", to: "EnumItem", message: Some(format!("Found unknown Enum.<<ENUM_NAME>> value '{}'", self)), }), } } } ]] -- FontWeight enum and implementation local function makeRustEnum(enum, default, numType: string) local name = tostring(enum) name = string.gsub(name, "^Enum.", "") local defaultName = tostring(default) defaultName = string.gsub(defaultName, "^Enum.", "") defaultName = string.gsub(defaultName, "^" .. name .. ".", "") local enumNames = "" local enumToNumbers = "" local numbersToEnum = "" local stringsToEnum = "" local enumToStrings = "" for _, enum in enum:GetEnumItems() do enumNames ..= `\n{enum.Name},` enumToNumbers ..= `\nSelf::{enum.Name} => {enum.Value},` numbersToEnum ..= `\n{enum.Value} => Some(Self::{enum.Name}),` stringsToEnum ..= `\n"{enum.Name}" => Ok(Self::{enum.Name}),` enumToStrings ..= `\nSelf::{enum.Name} => "{enum.Name}",` end local mappings: { [string]: string } = { ["<<ENUM_NAME>>"] = name, ["<<DEFAULT_NAME>>"] = defaultName, ["<<NUMBER_TYPE>>"] = numType, ["<<ENUM_NAMES>>"] = enumNames, ["<<ENUM_TO_NUMBERS>>"] = enumToNumbers, ["<<ENUM_TO_STRINGS>>"] = enumToStrings, ["<<NUMBERS_TO_ENUM>>"] = numbersToEnum, ["<<STRINGS_TO_ENUM>>"] = stringsToEnum, } local result = ENUM_IMPLEMENTATION for key, replacement in mappings do result = string.gsub(result, "(\t*)" .. key, function(tabbing) local spacing = string.gsub(tabbing, "\t", " ") local inner = string.gsub(replacement, "\n", "\n" .. spacing) inner = string.gsub(inner, "^\n+", "") return inner end) end return result end contents ..= makeRustEnum(Enum.FontWeight, Enum.FontWeight.Regular, "u16") contents ..= "\n" contents ..= makeRustEnum(Enum.FontStyle, Enum.FontStyle.Normal, "u8") contents ..= "\n" -- Font constant map from enum to font data local longestNameLen = 0 local longestFamilyLen = 0 local longestWeightLen = 0 for _, enum in Enum.Font:GetEnumItems() do longestNameLen = math.max(longestNameLen, #enum.Name) if enum ~= Enum.Font.Unknown then local font = Font.fromEnum(enum) longestFamilyLen = math.max(longestFamilyLen, #font.Family) longestWeightLen = math.max(longestWeightLen, #font.Weight.Name) end end contents ..= "\n#[rustfmt::skip]\nconst FONT_ENUM_MAP: &[(&str, Option<FontData>)] = &[\n" for _, enum in Enum.Font:GetEnumItems() do if enum == Enum.Font.Unknown then contents ..= string.format( ' ("Unknown",%s None),\n', string.rep(" ", longestNameLen - #enum.Name) ) else local font = Font.fromEnum(enum) contents ..= string.format( ' ("%s",%s Some(("%s",%s FontWeight::%s,%s FontStyle::%s))),\n', enum.Name, string.rep(" ", longestNameLen - #enum.Name), font.Family, string.rep(" ", longestFamilyLen - #font.Family), font.Weight.Name, string.rep(" ", longestWeightLen - #font.Weight.Name), font.Style.Name ) end end contents ..= "];\n" print(contents)