diff --git a/rbx_binary/src/tests/models.rs b/rbx_binary/src/tests/models.rs index 3965e2c3e..1f20772bd 100644 --- a/rbx_binary/src/tests/models.rs +++ b/rbx_binary/src/tests/models.rs @@ -63,4 +63,5 @@ binary_tests! { text_label_with_font, gui_inset_and_font_migration, folder_with_cframe_attributes, + folder_with_font_attribute, } diff --git a/rbx_binary/src/tests/snapshots/rbx_binary__tests__util__folder-with-font-attribute__decoded.snap b/rbx_binary/src/tests/snapshots/rbx_binary__tests__util__folder-with-font-attribute__decoded.snap new file mode 100644 index 000000000..5874ddb1a --- /dev/null +++ b/rbx_binary/src/tests/snapshots/rbx_binary__tests__util__folder-with-font-attribute__decoded.snap @@ -0,0 +1,22 @@ +--- +source: rbx_binary/src/tests/util.rs +expression: decoded_viewed +--- +- referent: referent-0 + name: Folder + class: Folder + properties: + Attributes: + Attributes: + AFontAttribute: + Font: + family: "rbxasset://fonts/families/Creepster.json" + weight: Regular + style: Normal + cachedFaceId: ~ + SourceAssetId: + Int64: -1 + Tags: + Tags: [] + children: [] + diff --git a/rbx_binary/src/tests/snapshots/rbx_binary__tests__util__folder-with-font-attribute__encoded.snap b/rbx_binary/src/tests/snapshots/rbx_binary__tests__util__folder-with-font-attribute__encoded.snap new file mode 100644 index 000000000..c9aecd3c9 --- /dev/null +++ b/rbx_binary/src/tests/snapshots/rbx_binary__tests__util__folder-with-font-attribute__encoded.snap @@ -0,0 +1,44 @@ +--- +source: rbx_binary/src/tests/util.rs +expression: text_roundtrip +--- +num_types: 1 +num_instances: 1 +chunks: + - Inst: + type_id: 0 + type_name: Folder + object_format: 0 + referents: + - 0 + - Prop: + type_id: 0 + prop_name: AttributesSerialize + prop_type: String + values: + - 01 00 00 00 0e 00 00 00 41 46 6f 6e 74 41 74 74 72 69 62 75 74 65 21 90 01 00 28 00 00 00 72 62 78 61 73 73 65 74 3a 2f 2f 66 6f 6e 74 73 2f 66 61 6d 69 6c 69 65 73 2f 43 72 65 65 70 73 74 65 72 2e 6a 73 6f 6e 00 00 00 00 + - Prop: + type_id: 0 + prop_name: Name + prop_type: String + values: + - Folder + - Prop: + type_id: 0 + prop_name: SourceAssetId + prop_type: Int64 + values: + - -1 + - Prop: + type_id: 0 + prop_name: Tags + prop_type: String + values: + - "" + - Prnt: + version: 0 + links: + - - 0 + - -1 + - End + diff --git a/rbx_binary/src/tests/snapshots/rbx_binary__tests__util__folder-with-font-attribute__input.snap b/rbx_binary/src/tests/snapshots/rbx_binary__tests__util__folder-with-font-attribute__input.snap new file mode 100644 index 000000000..db974b7e1 --- /dev/null +++ b/rbx_binary/src/tests/snapshots/rbx_binary__tests__util__folder-with-font-attribute__input.snap @@ -0,0 +1,48 @@ +--- +source: rbx_binary/src/tests/util.rs +expression: text_decoded +--- +num_types: 1 +num_instances: 1 +chunks: + - Meta: + entries: + - - ExplicitAutoJoints + - "true" + - Inst: + type_id: 0 + type_name: Folder + object_format: 0 + referents: + - 0 + - Prop: + type_id: 0 + prop_name: AttributesSerialize + prop_type: String + values: + - 01 00 00 00 0e 00 00 00 41 46 6f 6e 74 41 74 74 72 69 62 75 74 65 21 90 01 00 28 00 00 00 72 62 78 61 73 73 65 74 3a 2f 2f 66 6f 6e 74 73 2f 66 61 6d 69 6c 69 65 73 2f 43 72 65 65 70 73 74 65 72 2e 6a 73 6f 6e 00 00 00 00 + - Prop: + type_id: 0 + prop_name: Name + prop_type: String + values: + - Folder + - Prop: + type_id: 0 + prop_name: SourceAssetId + prop_type: Int64 + values: + - -1 + - Prop: + type_id: 0 + prop_name: Tags + prop_type: String + values: + - "" + - Prnt: + version: 0 + links: + - - 0 + - -1 + - End + diff --git a/rbx_types/CHANGELOG.md b/rbx_types/CHANGELOG.md index 9ccd90b73..75895b10f 100644 --- a/rbx_types/CHANGELOG.md +++ b/rbx_types/CHANGELOG.md @@ -5,11 +5,13 @@ * Changed `BinaryString`'s non-human readable serde implementation to be identical to `Vec`. ([#276]) * Added `Font::new` and `Font::regular` constructors. ([#283]) * Added support for `CFrame` values in attributes. ([#296]) +* Added support for `Font` values in attributes. ([#299]) [#271]: https://github.com/rojo-rbx/rbx-dom/pull/271 [#276]: https://github.com/rojo-rbx/rbx-dom/pull/276 [#283]: https://github.com/rojo-rbx/rbx-dom/pull/283 [#296]: https://github.com/rojo-rbx/rbx-dom/pull/296 +[#299]: https://github.com/rojo-rbx/rbx-dom/pull/299 ## 1.5.0 (2023-04-22) * Implemented `Font`. ([#248]) diff --git a/rbx_types/src/attributes/error.rs b/rbx_types/src/attributes/error.rs index b60201f4d..06386239e 100644 --- a/rbx_types/src/attributes/error.rs +++ b/rbx_types/src/attributes/error.rs @@ -35,4 +35,12 @@ pub(crate) enum AttributeError { #[error("couldn't read bytes to deserialize {0}")] ReadType(&'static str), + + #[error("font contained invalid UTF-8 in {field}")] + FontBadUnicode { + #[source] + source: FromUtf8Error, + + field: &'static str, + }, } diff --git a/rbx_types/src/attributes/reader.rs b/rbx_types/src/attributes/reader.rs index 3c614dedd..e14ca4b2c 100644 --- a/rbx_types/src/attributes/reader.rs +++ b/rbx_types/src/attributes/reader.rs @@ -4,9 +4,9 @@ use std::{ }; use crate::{ - BinaryString, BrickColor, CFrame, Color3, ColorSequence, ColorSequenceKeypoint, Matrix3, - NumberRange, NumberSequence, NumberSequenceKeypoint, Rect, UDim, UDim2, Variant, VariantType, - Vector2, Vector3, + BinaryString, BrickColor, CFrame, Color3, ColorSequence, ColorSequenceKeypoint, Font, + FontStyle, FontWeight, Matrix3, NumberRange, NumberSequence, NumberSequenceKeypoint, Rect, + UDim, UDim2, Variant, VariantType, Vector2, Vector3, }; use super::{type_id, AttributeError}; @@ -161,6 +161,43 @@ pub(crate) fn read_attributes( } .into(), + VariantType::Font => { + let weight = read_u16(&mut value)?; + let style = read_u8(&mut value)?; + + let family = { + let buf = read_string(&mut value)?; + + String::from_utf8(buf).map_err(|source| AttributeError::FontBadUnicode { + source, + field: "family", + })? + }; + + let cached_face_id = { + let buf = read_string(&mut value)?; + + if buf.is_empty() { + None + } else { + Some(String::from_utf8(buf).map_err(|source| { + AttributeError::FontBadUnicode { + source, + field: "cached_face_id", + } + })?) + } + }; + + Font { + family, + weight: FontWeight::from_u16(weight).unwrap_or_default(), + style: FontStyle::from_u8(style).unwrap_or_default(), + cached_face_id, + } + } + .into(), + other => return Err(AttributeError::UnsupportedVariantType(other)), }; @@ -176,6 +213,12 @@ fn read_u8(mut reader: R) -> io::Result { Ok(bytes[0]) } +fn read_u16(mut reader: R) -> io::Result { + let mut bytes = [0u8; 2]; + reader.read_exact(&mut bytes)?; + Ok(u16::from_le_bytes(bytes)) +} + fn read_i32(mut reader: R) -> io::Result { let mut bytes = [0u8; 4]; reader.read_exact(&mut bytes)?; diff --git a/rbx_types/src/attributes/type_id.rs b/rbx_types/src/attributes/type_id.rs index e891bc2e7..4350af7a9 100644 --- a/rbx_types/src/attributes/type_id.rs +++ b/rbx_types/src/attributes/type_id.rs @@ -49,4 +49,5 @@ type_ids! { // ??? => 0x1A, NumberRange => 0x1B, Rect => 0x1C, + Font => 0x21, } diff --git a/rbx_types/src/attributes/writer.rs b/rbx_types/src/attributes/writer.rs index 15c53c00f..792593f78 100644 --- a/rbx_types/src/attributes/writer.rs +++ b/rbx_types/src/attributes/writer.rs @@ -92,6 +92,15 @@ pub(crate) fn write_attributes( write_vector3(&mut writer, matrix.z)?; } } + Variant::Font(font) => { + write_u16(&mut writer, font.weight.as_u16())?; + write_u8(&mut writer, font.style.as_u8())?; + write_string(&mut writer, &font.family)?; + write_string( + &mut writer, + &font.cached_face_id.clone().unwrap_or_default(), + )?; + } other_variant => unreachable!("variant {:?} was not implemented", other_variant), } @@ -112,6 +121,10 @@ fn write_u32(mut writer: W, n: u32) -> io::Result<()> { writer.write_all(&n.to_le_bytes()[..]) } +fn write_u16(mut writer: W, n: u16) -> io::Result<()> { + writer.write_all(&n.to_le_bytes()[..]) +} + fn write_u8(mut writer: W, n: u8) -> io::Result<()> { writer.write_all(&n.to_le_bytes()[..]) } diff --git a/rbx_xml/src/tests/models.rs b/rbx_xml/src/tests/models.rs index f8103cbb8..6bed5f2ab 100644 --- a/rbx_xml/src/tests/models.rs +++ b/rbx_xml/src/tests/models.rs @@ -64,4 +64,5 @@ model_tests! { text_label_with_font, gui_inset_and_font_migration, folder_with_cframe_attributes, + folder_with_font_attribute, } diff --git a/rbx_xml/src/tests/snapshots/rbx_xml__tests__folder-with-font-attribute__decoded.snap b/rbx_xml/src/tests/snapshots/rbx_xml__tests__folder-with-font-attribute__decoded.snap new file mode 100644 index 000000000..bd0aa5b48 --- /dev/null +++ b/rbx_xml/src/tests/snapshots/rbx_xml__tests__folder-with-font-attribute__decoded.snap @@ -0,0 +1,22 @@ +--- +source: rbx_xml/src/tests/mod.rs +expression: "DomViewer::new().view_children(&decoded)" +--- +- referent: referent-0 + name: Folder + class: Folder + properties: + Attributes: + Attributes: + AFontAttribute: + Font: + family: "rbxasset://fonts/families/Creepster.json" + weight: Regular + style: Normal + cachedFaceId: ~ + SourceAssetId: + Int64: -1 + Tags: + Tags: [] + children: [] + diff --git a/rbx_xml/src/tests/snapshots/rbx_xml__tests__folder-with-font-attribute__roundtrip.snap b/rbx_xml/src/tests/snapshots/rbx_xml__tests__folder-with-font-attribute__roundtrip.snap new file mode 100644 index 000000000..41156677a --- /dev/null +++ b/rbx_xml/src/tests/snapshots/rbx_xml__tests__folder-with-font-attribute__roundtrip.snap @@ -0,0 +1,22 @@ +--- +source: rbx_xml/src/tests/mod.rs +expression: "DomViewer::new().view_children(&roundtrip)" +--- +- referent: referent-0 + name: Folder + class: Folder + properties: + Attributes: + Attributes: + AFontAttribute: + Font: + family: "rbxasset://fonts/families/Creepster.json" + weight: Regular + style: Normal + cachedFaceId: ~ + SourceAssetId: + Int64: -1 + Tags: + Tags: [] + children: [] +