diff --git a/crates/typst-library/src/foundations/float.rs b/crates/typst-library/src/foundations/float.rs index bb3232ee8..c3d4e0e73 100644 --- a/crates/typst-library/src/foundations/float.rs +++ b/crates/typst-library/src/foundations/float.rs @@ -128,16 +128,21 @@ impl f64 { #[default(Endianness::Little)] endian: Endianness, ) -> StrResult { - // Convert slice to an array of length 8. - let buf: [u8; 8] = match bytes.as_ref().try_into() { - Ok(buffer) => buffer, - Err(_) => bail!("bytes must have a length of exactly 8"), + // Convert slice to an array of length 4 or 8. + if let Ok(buffer) = <[u8; 8]>::try_from(bytes.as_ref()) { + return Ok(match endian { + Endianness::Little => f64::from_le_bytes(buffer), + Endianness::Big => f64::from_be_bytes(buffer), + }); + }; + if let Ok(buffer) = <[u8; 4]>::try_from(bytes.as_ref()) { + return Ok(match endian { + Endianness::Little => f32::from_le_bytes(buffer), + Endianness::Big => f32::from_be_bytes(buffer), + } as f64); }; - Ok(match endian { - Endianness::Little => f64::from_le_bytes(buf), - Endianness::Big => f64::from_be_bytes(buf), - }) + bail!("bytes must have a length of 4 or 8"); } /// Converts a float to bytes. @@ -153,13 +158,25 @@ impl f64 { #[named] #[default(Endianness::Little)] endian: Endianness, - ) -> Bytes { - match endian { - Endianness::Little => self.to_le_bytes(), - Endianness::Big => self.to_be_bytes(), - } - .as_slice() - .into() + #[named] + #[default(8)] + size: u32, + ) -> StrResult { + Ok(match size { + 8 => match endian { + Endianness::Little => self.to_le_bytes(), + Endianness::Big => self.to_be_bytes(), + } + .as_slice() + .into(), + 4 => match endian { + Endianness::Little => (self as f32).to_le_bytes(), + Endianness::Big => (self as f32).to_be_bytes(), + } + .as_slice() + .into(), + _ => bail!("size must be either 4 or 8"), + }) } } diff --git a/tests/suite/foundations/float.typ b/tests/suite/foundations/float.typ index 2e9e07f2a..716ecd6b6 100644 --- a/tests/suite/foundations/float.typ +++ b/tests/suite/foundations/float.typ @@ -53,8 +53,13 @@ #test(1.0.to-bytes(), bytes((0, 0, 0, 0, 0, 0, 240, 63))) #test(1.0.to-bytes(endian: "big"), bytes((63, 240, 0, 0, 0, 0, 0, 0))) +#test(float.from-bytes(bytes((0, 0, 32, 64))), 2.5) +#test(float.from-bytes(bytes((64, 32, 0, 0)), endian: "big"), 2.5) +#test(2.5.to-bytes(size: 4), bytes((0, 0, 32, 64))) +#test(2.5.to-bytes(size: 4, endian: "big"), bytes((64, 32, 0, 0))) + --- float-from-bytes-bad-length --- -// Error: 2-54 bytes must have a length of exactly 8 +// Error: 2-54 bytes must have a length of 4 or 8 #float.from-bytes(bytes((0, 0, 0, 0, 0, 0, 0, 1, 0))) --- float-repr ---