Skip to content

Commit de8bafc

Browse files
authored
Adds resolve function, ResolvedSchema, and ResolvedType (#245)
1 parent cae9e1d commit de8bafc

File tree

13 files changed

+814
-39
lines changed

13 files changed

+814
-39
lines changed

ion-schema/src/model/bag.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ impl<T> Bag<T> {
5858
pub fn iter(&self) -> impl Iterator<Item = &T> {
5959
self.items.iter()
6060
}
61+
62+
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
63+
self.items.iter_mut()
64+
}
6165
}
6266

6367
impl<T> IntoIterator for Bag<T> {

ion-schema/src/model/constraints/annotations/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ impl ConstraintName for Annotations {
3232
pub struct Annotations {
3333
variant: AnnotationsVariant,
3434
}
35-
impl_type_ref_walker!(Annotations, as_annotations_v2_standard());
35+
impl_type_ref_walker!(Annotations, as_annotations_v2_standard_mut());
3636

3737
impl Annotations {
3838
pub fn as_annotations_v1(&self) -> Option<&AnnotationsV1> {
@@ -56,6 +56,14 @@ impl Annotations {
5656
None
5757
}
5858
}
59+
60+
pub fn as_annotations_v2_standard_mut(&mut self) -> Option<&mut AnnotationsV2Standard> {
61+
if let AnnotationsVariant::V2Standard(ref mut variant) = &mut self.variant {
62+
Some(variant)
63+
} else {
64+
None
65+
}
66+
}
5967
}
6068

6169
#[derive(Debug, PartialEq, Clone)]

ion-schema/src/model/constraints/any_constraint.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ macro_rules! any_constraint {
3939
)+
4040

4141
impl TypeRefWalker for AnyConstraint {
42-
fn walk<V: TypeRefVisitor>(&self, visitor: &mut V) {
42+
fn walk<V: TypeRefVisitor>(&mut self, visitor: &mut V) {
4343
match self {
4444
$(AnyConstraint::$name(constraint) => constraint.walk(visitor),
4545
)+

ion-schema/src/model/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ pub use schema_header::*;
1818
pub use type_argument::*;
1919
pub use type_definition::*;
2020
pub use type_reference::*;
21+
pub use variable_type_argument::*;

ion-schema/src/model/schema.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl From<Element> for SchemaItem {
3333
}
3434

3535
impl TypeRefWalker for SchemaItem {
36-
fn walk<V: TypeRefVisitor>(&self, visitor: &mut V) {
36+
fn walk<V: TypeRefVisitor>(&mut self, visitor: &mut V) {
3737
if let SchemaItem::Type(_, t) = self {
3838
t.walk(visitor)
3939
}
@@ -84,6 +84,25 @@ impl SchemaDocument {
8484
self.items.iter()
8585
}
8686

87+
/// Iterate all types declared in this schema document
88+
pub fn types(&self) -> impl Iterator<Item = (&str, &TypeDefinition)> {
89+
self.items.iter().filter_map(|item| match item {
90+
SchemaItem::Type(name, def) => Some((name.as_str(), def)),
91+
_ => None,
92+
})
93+
}
94+
95+
/// Gets the [`SchemaHeader`], if this schema document has a header.
96+
pub fn header(&self) -> Option<&SchemaHeader> {
97+
self.items.iter().find_map(|item| {
98+
if let SchemaItem::Header(header) = item {
99+
Some(header)
100+
} else {
101+
None
102+
}
103+
})
104+
}
105+
87106
/// Get a type from the schema, by name.
88107
pub fn get_type(&self, name: &str) -> Option<&TypeDefinition> {
89108
self.items.iter().find_map(|item| match item {
@@ -92,6 +111,17 @@ impl SchemaDocument {
92111
})
93112
}
94113

114+
/// Iterate all types declared in this schema definition
115+
pub(crate) fn indexed_type_names(&self) -> impl Iterator<Item = (usize, &String)> {
116+
self.items
117+
.iter()
118+
.enumerate()
119+
.filter_map(|(idx, item)| match item {
120+
SchemaItem::Type(name, _) => Some((idx, name)),
121+
_ => None,
122+
})
123+
}
124+
95125
pub(crate) fn get_type_idx_by_name(&self, name: &str) -> Option<usize> {
96126
self.items
97127
.iter()

ion-schema/src/model/schema_header.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,25 @@ impl Import {
6464
}),
6565
}
6666
}
67+
68+
/// The Schema ID that this [`Import`] is targeting.
69+
pub fn schema_id(&self) -> &str {
70+
&self.schema_id
71+
}
72+
73+
/// The (optional) type that this [`Import`] is targeting.
74+
pub fn type_name(&self) -> Option<&str> {
75+
self.type_import
76+
.as_ref()
77+
.map(|type_import| type_import.type_name.as_str())
78+
}
79+
80+
/// The (optional) alias for the type that this [`Import`] is targeting.
81+
pub fn type_alias(&self) -> Option<&str> {
82+
self.type_import
83+
.as_ref()
84+
.and_then(|type_import| type_import.alias.as_deref())
85+
}
6786
}
6887

6988
/// Builds a [`SchemaHeader`].

ion-schema/src/model/type_argument.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ enum TypeArgumentKind {
5252
}
5353

5454
impl TypeRefWalker for TypeArgument {
55-
fn walk<V: TypeRefVisitor>(&self, visitor: &mut V) {
56-
match &self.kind {
57-
TypeArgumentKind::TypeReference(ref type_ref) => visitor.visit(type_ref),
58-
TypeArgumentKind::InlineType(type_def) => type_def.walk(visitor),
55+
fn walk<V: TypeRefVisitor>(&mut self, visitor: &mut V) {
56+
match &mut self.kind {
57+
TypeArgumentKind::TypeReference(ref mut type_ref) => visitor.visit(type_ref),
58+
TypeArgumentKind::InlineType(ref mut type_def) => type_def.walk(visitor),
5959
}
6060
}
6161
}

ion-schema/src/model/type_reference.rs

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use crate::internal_traits::{LoaderContext, ReadFromIsl, WriteAsIsl, WriteContext};
55
use crate::ion_extension::StructExtensions;
6-
use crate::model::type_definition::TypeDefinition;
6+
use crate::resolver::TypeCoordinates;
77
use crate::result::{invalid_schema_error, IonSchemaResult};
88
use crate::IslVersion;
99
use ion_rs::{Element, StructWriter, Value, ValueWriter};
@@ -13,17 +13,27 @@ use ion_rs::{Element, StructWriter, Value, ValueWriter};
1313
pub struct TypeReference {
1414
schema_id: Option<String>,
1515
type_name: String,
16-
// Not exposed in public API.
17-
// Initially `None`, but changed to `Some(_)` when resolving the schemas
18-
// TODO: resolved: Cell<Option<...>>,
16+
// Not exposed in public API. Initially `None`, but changed to `Some(_)` when resolving the schemas
17+
resolved_type_coordinates: Option<TypeCoordinates>,
1918
}
2019

2120
impl TypeReference {
22-
// TODO: Determine if this needs to be pub
23-
pub(crate) fn imported<A: Into<String>, B: Into<String>>(schema_id: A, type_name: B) -> Self {
21+
/// Creates a `TypeReference` for a type name that is defined in or imported to the current
22+
/// [`SchemaDocument`].
23+
fn local<S: Into<String>>(type_name: S) -> Self {
24+
TypeReference {
25+
schema_id: None,
26+
type_name: type_name.into(),
27+
resolved_type_coordinates: None,
28+
}
29+
}
30+
31+
/// Creates a `TypeReference` that is an inline import from another schema.
32+
pub fn imported<A: Into<String>, B: Into<String>>(schema_id: A, type_name: B) -> Self {
2433
TypeReference {
2534
schema_id: Some(schema_id.into()),
2635
type_name: type_name.into(),
36+
resolved_type_coordinates: None,
2737
}
2838
}
2939

@@ -35,20 +45,19 @@ impl TypeReference {
3545
self.type_name.as_str()
3646
}
3747

38-
/// Returns an immutable borrow of the [TypeDefinition] to which this [TypeReference] refers.
39-
pub fn get(&self) -> Option<&TypeDefinition> {
40-
todo!()
48+
pub(crate) fn type_coordinates(&self) -> Option<TypeCoordinates> {
49+
self.resolved_type_coordinates
4150
}
4251

43-
// TODO: functions for setting the resolved type
52+
/// Sets the [`TypeCoordinates`] of this `TypeReference`.
53+
pub(crate) fn set_type_coordinates(&mut self, type_coordinates: Option<TypeCoordinates>) {
54+
self.resolved_type_coordinates = type_coordinates
55+
}
4456
}
4557

4658
impl<T: Into<String>> From<T> for TypeReference {
4759
fn from(value: T) -> Self {
48-
TypeReference {
49-
schema_id: None,
50-
type_name: value.into(),
51-
}
60+
TypeReference::local(value)
5261
}
5362
}
5463

@@ -105,10 +114,7 @@ mod tests {
105114
#[test]
106115
fn from_string() {
107116
let from_value = "foo";
108-
let expected = TypeReference {
109-
schema_id: None,
110-
type_name: "foo".to_string(),
111-
};
117+
let expected = TypeReference::local("foo");
112118
assert_eq!(expected, from_value.into())
113119
}
114120

@@ -118,13 +124,14 @@ mod tests {
118124
let expected = TypeReference {
119125
schema_id: Some("foo".to_string()),
120126
type_name: "bar".to_string(),
127+
resolved_type_coordinates: None,
121128
};
122129
assert_eq!(expected, actual)
123130
}
124131

125132
#[rstest]
126-
#[case::type_name("foo", TypeReference { schema_id: None, type_name: "foo".to_string() })]
127-
#[case::inline_import("{id:\"foo.isl\",type:bar}", TypeReference { schema_id: Some("foo.isl".to_string()), type_name: "bar".to_string() } )]
133+
#[case::type_name("foo", TypeReference::local("foo"))]
134+
#[case::inline_import("{id:\"foo.isl\",type:bar}", TypeReference::imported("foo.isl", "bar"))]
128135
fn type_reference_try_read_ok(#[case] ion: &str, #[case] expected: TypeReference) {
129136
let expected = Ok(expected);
130137
let element = Element::read_one(ion).unwrap();

ion-schema/src/resolver/mod.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,39 @@
33

44
use crate::model::SchemaDocument;
55

6+
mod resolve_fn;
7+
mod resolved_schema;
68
mod type_ref_visitor;
79

10+
pub use resolve_fn::resolve;
11+
pub use resolve_fn::unresolve;
12+
pub use resolved_schema::*;
813
pub(crate) use type_ref_visitor::*;
914

15+
/// A schema index and type index.
16+
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
17+
pub(crate) struct TypeCoordinates(usize, usize);
18+
impl TypeCoordinates {
19+
#[cfg(test)]
20+
pub(crate) fn new(s_idx: usize, t_idx: usize) -> Self {
21+
TypeCoordinates(s_idx, t_idx)
22+
}
23+
24+
fn schema_idx(&self) -> usize {
25+
self.0
26+
}
27+
fn type_idx(&self) -> usize {
28+
self.1
29+
}
30+
}
31+
1032
#[derive(Debug)]
1133
pub(crate) struct SchemaStore {
1234
schemas: Vec<(String, SchemaDocument)>,
1335
}
36+
37+
impl SchemaStore {
38+
pub(crate) fn get_schema(&self, schema_idx: usize) -> &SchemaDocument {
39+
&self.schemas[schema_idx].1
40+
}
41+
}

0 commit comments

Comments
 (0)