//! The `margin_classify` generated function's place in the engine: CSS 2.1 8.3.1's //! decision, for one box, of how its margins take part in collapsing, isolated behind one //! function with plain-data inputs and outputs (`roadmap.md` -> "Phase 1 -- Engine //! bootstrap" step 4). The types a candidate implements against are re-exported from //! [`crate::margin_classify_types`] so `layout::margin_classify::...` names them; this //! module says how the engine fills them. [`crate::margin_combine`] holds the other half of //! the margin-collapsing pair, which the block-flow function asks once it has collected a //! group of adjoining margins. //! //! The block-flow function ([`crate::block_flow`]) asks for the answer through the plain //! function `fragment.rs` `call_block_flow` hands it, `BlockFlowFunctions::classify` //! (`margin_classify_call_site.txt`, which a job's prompt carries), for a box of block //! children and for a box whose line boxes, table rows or grid items another walk placed. //! //! **Written against any types file.** A job's types file is model-written and chooses its //! inputs from the engine's fixed list ([`crate::margin_classify_engine`]), so nothing here //! names an input field. The engine builds a [`MarginClassifyEngineValues`] and calls //! through [`call`], which fills the inputs with [`inputs_from`] (written by `build.rs` from //! the types file in place). [`classify_baseline`] reads no input, so it stands in for the //! function whatever the types file holds. pub use crate::margin_classify_engine::{MarginClassifyEngineAnswer, MarginClassifyEngineValues}; pub use crate::margin_classify_types::{MarginClassifyInputs, MarginClassifyOutputs, MarginClassifyResolver}; use dom::node::NodeId; include!(concat!(env!("OUT_DIR"), "/margin_classify_inputs_from.rs")); /// One call the engine made to the function for a box, as `fragment.rs` records it /// (`crate::call_recording`): the box and the engine's values for it. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct MarginClassifyCall { pub node: NodeId, /// The engine's values at the call (`inputs_from` turns them into what the resolver /// was handed). pub values: MarginClassifyEngineValues, } /// Asks `resolver` about the box `values` describes: fills the types file's inputs from /// `values` ([`inputs_from`]) and returns the answer. How the engine calls every /// `margin_classify` resolver. pub fn call(resolver: MarginClassifyResolver, values: &MarginClassifyEngineValues) -> MarginClassifyOutputs { resolver(&inputs_from(values)) } /// Deliberately wrong starting candidate: nothing adjoins, nothing self-collapses, /// nothing escapes past a box's own border or padding. pub fn classify_baseline(_inputs: &MarginClassifyInputs) -> MarginClassifyOutputs { MarginClassifyOutputs { self_collapsing: false, top_open: false, bottom_open: false, sibling_adjoin: false } } #[cfg(test)] mod tests { use super::*; fn values() -> MarginClassifyEngineValues { MarginClassifyEngineValues { has_top_border_or_padding: false, has_bottom_border_or_padding: false, establishes_bfc: false, height_is_auto: true, height_is_explicit_zero: false, no_in_flow_content: true, } } #[test] fn baseline_never_collapses_or_opens() { let out = call(classify_baseline, &values()); assert!(!out.self_collapsing); assert!(!out.top_open); assert!(!out.bottom_open); assert!(!out.sibling_adjoin); } #[test] fn inputs_are_the_engine_values_of_the_same_name() { let mut v = values(); v.establishes_bfc = true; v.height_is_auto = false; let i = inputs_from(&v); assert!(i.establishes_bfc); assert!(!i.height_is_auto); assert!(i.no_in_flow_content); } }