mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Refuse record layouts wider than the frame tier's alignment
This commit is contained in:
@@ -155,6 +155,11 @@ impl Default for ElementWrite {
|
||||
}
|
||||
}
|
||||
|
||||
/// The widest alignment a record may need. Frames are a `Vec<u64>`, lanes
|
||||
/// stride at a multiple of 8, and run slabs come from `alloc_scratch::<u64>`,
|
||||
/// so nothing below a record can promise more.
|
||||
pub const MAX_ALIGN: usize = 8;
|
||||
|
||||
/// A record layout: the element at offset 0, then the written attributes in
|
||||
/// canonical order (descending alignment, then size, then name, then level).
|
||||
/// Layouts are derived data, a pure function of the upstream write set.
|
||||
@@ -198,8 +203,9 @@ impl Layout {
|
||||
|
||||
/// The union of this layout's fields and `writes` over `element` at
|
||||
/// `depth`, in canonical order. A (name, level) written at a different
|
||||
/// size is a type conflict and panics; the census keeps declared names to
|
||||
/// one type, so this only fires on wiring bugs.
|
||||
/// size is a type conflict and panics, as does an element or attribute
|
||||
/// wider than [`MAX_ALIGN`]; the census keeps declared names to one type,
|
||||
/// so these only fire on wiring bugs.
|
||||
pub fn with_writes(&self, depth: u8, element: ElementWrite, writes: &[FieldWrite]) -> Layout {
|
||||
let mut merged: Vec<FieldWrite> = self.fields.iter().map(FieldDesc::as_write).collect();
|
||||
for &write in writes {
|
||||
@@ -208,6 +214,10 @@ impl Layout {
|
||||
None => merged.push(write),
|
||||
}
|
||||
}
|
||||
assert!(element.align <= MAX_ALIGN, "a record element aligns to at most {MAX_ALIGN} bytes, but this one needs {}", element.align);
|
||||
for write in &merged {
|
||||
assert!(write.align <= MAX_ALIGN, "attribute `{}` aligns to at most {MAX_ALIGN} bytes, but needs {}", write.name, write.align);
|
||||
}
|
||||
merged.sort_by(|a, b| b.align.cmp(&a.align).then(b.size.cmp(&a.size)).then(a.name.cmp(b.name)).then(a.level.cmp(&b.level)));
|
||||
let mut offset = element.size;
|
||||
let mut align = element.align.max(1);
|
||||
@@ -619,6 +629,18 @@ mod tests {
|
||||
assert_eq!(layout.align, 8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "a record element aligns to at most 8 bytes")]
|
||||
fn an_over_aligned_element_is_refused_at_wiring() {
|
||||
Layout::default().with_writes(0, element_write::<u128>(), &[]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "attribute `wide` aligns to at most 8 bytes")]
|
||||
fn an_over_aligned_attribute_is_refused_at_wiring() {
|
||||
Layout::default().with_writes(0, element_write::<f64>(), &[sized_field("wide", 16, 16)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "two different types")]
|
||||
fn type_conflicts_panic() {
|
||||
|
||||
Reference in New Issue
Block a user