substrait/parse/text/simple_extensions/
file.rs1use super::{CustomType, SimpleExtensions, SimpleExtensionsError};
4use crate::parse::Parse;
5use crate::parse::text::simple_extensions::extensions::TypeContext;
6use crate::text::simple_extensions::SimpleExtensions as RawExtensions;
7use crate::urn::Urn;
8use std::io::Read;
9
10#[derive(Debug)]
15pub struct ExtensionFile {
16 pub(crate) urn: Urn,
18 pub(crate) extension: SimpleExtensions,
20}
21
22impl ExtensionFile {
23 pub fn empty(urn: Urn) -> Self {
25 let extension = SimpleExtensions::default();
26 Self { urn, extension }
27 }
28
29 pub fn create(extensions: RawExtensions) -> Result<Self, SimpleExtensionsError> {
31 let mut ctx = TypeContext::default();
33 let file = Parse::parse(extensions, &mut ctx)?;
34
35 Ok(file)
38 }
39
40 pub fn get_type(&self, name: &str) -> Option<&CustomType> {
42 self.extension.get_type(name)
43 }
44
45 pub fn types(&self) -> impl Iterator<Item = &CustomType> {
47 self.extension.types()
48 }
49
50 pub fn urn(&self) -> &Urn {
52 &self.urn
53 }
54
55 pub fn extension(&self) -> &SimpleExtensions {
57 &self.extension
58 }
59
60 pub fn into_raw(self) -> RawExtensions {
63 self.into()
64 }
65
66 pub fn to_raw(&self) -> RawExtensions {
69 super::extensions::to_raw_extensions(self.urn.clone(), self.extension.clone())
70 }
71
72 pub fn read<R: Read>(reader: R) -> Result<Self, SimpleExtensionsError> {
77 let raw: RawExtensions = serde_yaml::from_reader(reader)?;
78 Self::create(raw)
79 }
80
81 pub fn read_from_str<S: AsRef<str>>(s: S) -> Result<Self, SimpleExtensionsError> {
83 let raw: RawExtensions = serde_yaml::from_str(s.as_ref())?;
84 Self::create(raw)
85 }
86}
87
88impl From<ExtensionFile> for RawExtensions {
89 fn from(file: ExtensionFile) -> Self {
90 let ExtensionFile { urn, extension } = file;
91 super::extensions::to_raw_extensions(urn, extension)
92 }
93}
94
95#[cfg(test)]
98mod tests {
99 use super::*;
100 use crate::parse::text::simple_extensions::types::ParameterConstraint as RawParameterType;
101
102 const YAML_PARAM_TEST: &str = r#"
103%YAML 1.2
104---
105urn: extension:example.com:param_test
106types:
107 - name: "ParamTest"
108 parameters:
109 - name: "K"
110 type: integer
111 min: 1
112 max: 10
113"#;
114
115 const YAML_UNRESOLVED_TYPE: &str = r#"
116%YAML 1.2
117---
118urn: extension:example.com:unresolved
119types:
120 - name: "Alias"
121 structure: List<Map<string, u!MissingType>>
122"#;
123
124 #[test]
125 fn yaml_round_trip_integer_param_bounds() {
126 let deserialized: RawExtensions = serde_yaml::from_str(YAML_PARAM_TEST).expect("parse ok");
127 let ext = ExtensionFile::create(deserialized.clone()).expect("create ok");
128 assert_eq!(ext.urn().to_string(), "extension:example.com:param_test");
129
130 let ty = ext.get_type("ParamTest").expect("type exists");
131 match &ty.parameters[..] {
132 [param] => match ¶m.param_type {
133 RawParameterType::Integer {
134 min: actual_min,
135 max: actual_max,
136 } => {
137 assert_eq!(actual_min, &Some(1));
138 assert_eq!(actual_max, &Some(10));
139 }
140 other => panic!("unexpected param type: {other:?}"),
141 },
142 other => panic!("unexpected parameters: {other:?}"),
143 }
144
145 let back = ext.to_raw();
146 assert_eq!(deserialized, back);
147 }
148
149 #[test]
150 fn unresolved_type_reference_errors() {
151 let err = ExtensionFile::read_from_str(YAML_UNRESOLVED_TYPE)
152 .expect_err("expected unresolved type reference error");
153
154 match err {
155 SimpleExtensionsError::UnresolvedTypeReference { type_name } => {
156 assert_eq!(type_name, "MissingType");
157 }
158 other => panic!("unexpected error type: {other:?}"),
159 }
160 }
161}