1use sim_kernel::{Cx, Result};
4
5use crate::base::Shape;
6use crate::compare::{ShapeRelationKind, relate_shapes};
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub enum ShapeQueryRelation {
11 Subsumes,
13 SubshapeOf,
15 Overlaps,
17}
18
19pub fn shape_query_matches(
24 cx: &mut Cx,
25 candidate: &dyn Shape,
26 wanted: &dyn Shape,
27 relation: ShapeQueryRelation,
28) -> Result<bool> {
29 let relation_kind = relate_shapes(cx, candidate, wanted, &[])?.kind;
30 Ok(match relation {
31 ShapeQueryRelation::Subsumes => matches!(
32 relation_kind,
33 ShapeRelationKind::Equal | ShapeRelationKind::RightSubshape
34 ),
35 ShapeQueryRelation::SubshapeOf => matches!(
36 relation_kind,
37 ShapeRelationKind::Equal | ShapeRelationKind::LeftSubshape
38 ),
39 ShapeQueryRelation::Overlaps => matches!(
40 relation_kind,
41 ShapeRelationKind::Equal
42 | ShapeRelationKind::LeftSubshape
43 | ShapeRelationKind::RightSubshape
44 | ShapeRelationKind::Overlap
45 ),
46 })
47}
48
49#[cfg(test)]
50mod tests {
51 use std::sync::Arc;
52
53 use sim_kernel::{Cx, DefaultFactory, NoopEvalPolicy};
54
55 use crate::{AnyShape, ExprKind, ExprKindShape, ShapeQueryRelation, shape_query_matches};
56
57 fn bare_cx() -> Cx {
58 Cx::new(
59 Arc::new(NoopEvalPolicy),
60 Arc::new(DefaultFactory),
61 sim_kernel::HandleSeed::new(0x5348_5101),
62 )
63 }
64
65 #[test]
66 fn directional_shape_queries_match_relation_semantics() {
67 let mut cx = bare_cx();
68 let any = AnyShape;
69 let string = ExprKindShape::new(ExprKind::String);
70
71 assert!(shape_query_matches(&mut cx, &any, &string, ShapeQueryRelation::Subsumes).unwrap());
72 assert!(
73 !shape_query_matches(&mut cx, &string, &any, ShapeQueryRelation::Subsumes).unwrap()
74 );
75 assert!(
76 shape_query_matches(&mut cx, &string, &any, ShapeQueryRelation::SubshapeOf).unwrap()
77 );
78 assert!(shape_query_matches(&mut cx, &string, &any, ShapeQueryRelation::Overlaps).unwrap());
79 }
80
81 #[test]
82 fn disjoint_shapes_do_not_overlap() {
83 let mut cx = bare_cx();
84 let string = ExprKindShape::new(ExprKind::String);
85 let number = ExprKindShape::new(ExprKind::Number);
86
87 assert!(
88 !shape_query_matches(&mut cx, &string, &number, ShapeQueryRelation::Overlaps).unwrap()
89 );
90 }
91}