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(Arc::new(NoopEvalPolicy), Arc::new(DefaultFactory))
59 }
60
61 #[test]
62 fn directional_shape_queries_match_relation_semantics() {
63 let mut cx = bare_cx();
64 let any = AnyShape;
65 let string = ExprKindShape::new(ExprKind::String);
66
67 assert!(shape_query_matches(&mut cx, &any, &string, ShapeQueryRelation::Subsumes).unwrap());
68 assert!(
69 !shape_query_matches(&mut cx, &string, &any, ShapeQueryRelation::Subsumes).unwrap()
70 );
71 assert!(
72 shape_query_matches(&mut cx, &string, &any, ShapeQueryRelation::SubshapeOf).unwrap()
73 );
74 assert!(shape_query_matches(&mut cx, &string, &any, ShapeQueryRelation::Overlaps).unwrap());
75 }
76
77 #[test]
78 fn disjoint_shapes_do_not_overlap() {
79 let mut cx = bare_cx();
80 let string = ExprKindShape::new(ExprKind::String);
81 let number = ExprKindShape::new(ExprKind::Number);
82
83 assert!(
84 !shape_query_matches(&mut cx, &string, &number, ShapeQueryRelation::Overlaps).unwrap()
85 );
86 }
87}