schemaorg_rs/profiles/google/
event.rs1use crate::types::SchemaNode;
7use crate::validation::ValidationDiagnostic as VD;
8
9use super::common::{recommend_property, require_property, validate_nested};
10use crate::profiles::{NodeProfileResult, Profile, TypeEligibility};
11
12pub struct GoogleEventProfile;
14
15impl Profile for GoogleEventProfile {
16 fn name(&self) -> &'static str {
17 "google"
18 }
19
20 fn version(&self) -> &'static str {
21 "2026-04-01"
22 }
23
24 fn source_url(&self) -> &'static str {
25 "https://developers.google.com/search/docs/appearance/structured-data/event"
26 }
27
28 fn supported_types(&self) -> &[&str] {
29 &["Event"]
30 }
31
32 fn evaluate_node(&self, node: &SchemaNode, _vocab_diagnostics: &[VD]) -> NodeProfileResult {
33 let type_name = node.types.first().map_or("Event", |t| t.as_str());
34 let path = type_name;
35 let mut diagnostics = Vec::new();
36 let mut required_missing = Vec::new();
37 let mut recommended_missing = Vec::new();
38
39 for prop in &["name", "startDate", "location"] {
41 if let Some(d) = require_property(node, prop, path) {
42 required_missing.push((*prop).to_string());
43 diagnostics.push(d);
44 }
45 }
46
47 for prop in &[
49 "image",
50 "description",
51 "endDate",
52 "offers",
53 "performer",
54 "organizer",
55 "eventStatus",
56 "eventAttendanceMode",
57 ] {
58 if let Some(d) = recommend_property(node, prop, path) {
59 recommended_missing.push((*prop).to_string());
60 diagnostics.push(d);
61 }
62 }
63
64 let place_diags =
66 validate_nested(node, "location", "Place", &["name", "address"], &[], path);
67 diagnostics.extend(place_diags);
68
69 let virtual_diags =
71 validate_nested(node, "location", "VirtualLocation", &["url"], &[], path);
72 diagnostics.extend(virtual_diags);
73
74 let eligible = required_missing.is_empty();
75
76 NodeProfileResult {
77 type_eligibility: TypeEligibility {
78 schema_type: type_name.to_string(),
79 eligible,
80 required_missing,
81 recommended_missing,
82 field_diagnostics: diagnostics,
83 },
84 }
85 }
86}