Skip to content

Commit cbd6f44

Browse files
committed
generic duplication key
1 parent f487258 commit cbd6f44

File tree

22 files changed

+1201
-1137
lines changed

22 files changed

+1201
-1137
lines changed

src/metagen/src/client_rs/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,11 +229,11 @@ impl RsClientManifest {
229229
) -> anyhow::Result<()> {
230230
render_static(dest, opts.hostcall)?;
231231

232-
self.types.render_full(dest)?;
233-
234232
let methods = self.node_metas.render_all_buffered()?;
235233
with_metas_namespace(dest, methods)?;
236234

235+
self.types.render_full(dest)?;
236+
237237
self.selections.render_all(dest)?;
238238

239239
self.render_query_graph(dest)?;
@@ -311,7 +311,7 @@ pub fn query_graph() -> QueryGraph {{
311311
let args_row = match &arg_ty {
312312
Some(arg_ty) => format!(
313313
"
314-
args: impl Into<NodeArgs<{arg_ty}>>"
314+
args: impl Into<NodeArgs<{arg_ty}>>"
315315
),
316316
None => "".into(),
317317
};

src/metagen/src/client_rs/selections.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ pub fn manifest_page(
211211
let selection = selection_for_field(variant);
212212
variants.push(UnionProp {
213213
name: struct_prop_name,
214-
variant_ty: variant.name().to_string(), // FIXME normalized??
214+
variant_ty: variant.name().to_string(),
215215
select_ty: selection,
216216
});
217217
}

src/typegraph/graph/src/conv/dedup.rs

Lines changed: 111 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,128 @@
11
// Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0.
22
// SPDX-License-Identifier: MPL-2.0
33

4-
use tg_schema::InjectionNode;
4+
use crate::{injection::InjectionNode, interlude::*, Type, TypeNodeExt as _, Wrap};
55

6-
use crate::{interlude::*, Type, TypeNodeExt as _, Wrap as _};
6+
use super::{key::TypeKeyEx, ConversionMap, MapItem, PathSegment, RelativePath, TypeKey};
77

8-
use super::{ConversionMap, MapItem, RelativePath, TypeKey};
8+
// TODO rename to `DuplicationKey`
9+
pub trait DupKey: std::hash::Hash + Eq + Clone {
10+
fn is_default(&self) -> bool;
11+
}
12+
13+
pub trait DuplicationKeyGenerator: Clone {
14+
type Key: DupKey;
15+
16+
fn gen_from_rpath(&self, rpath: &RelativePath) -> Self::Key;
17+
fn gen_from_type(&self, ty: &Type) -> Self::Key;
18+
19+
fn apply_path_segment(&self, key: &Self::Key, path_seg: &PathSegment) -> Self::Key;
20+
21+
fn find_type_in_rpath(
22+
&self,
23+
ty: &Type,
24+
rpath: &RelativePath,
25+
schema: &tg_schema::Typegraph,
26+
) -> bool {
27+
use RelativePath as RP;
28+
match rpath {
29+
RP::Function(_) => false,
30+
RP::NsObject(_) => false,
31+
RP::Input(p) => {
32+
let owner = p.owner.upgrade().expect("no strong pointer for type");
33+
let input_type = match &schema.types[owner.base.key.0 as usize] {
34+
tg_schema::TypeNode::Function { data, .. } => data.input,
35+
_ => unreachable!("expected a function node"),
36+
};
37+
let xkey = TypeKeyEx(ty.idx(), self.gen_from_type(ty));
38+
let mut cursor = TypeKeyEx(
39+
input_type,
40+
self.gen_from_rpath(&RelativePath::input(Arc::downgrade(&owner), vec![])),
41+
);
42+
// let mut cursor = TypeKeyEx(input_type, DuplicationKey { injection });
43+
for seg in &p.path {
44+
let next_dkey = self.apply_path_segment(&cursor.1, seg);
45+
// FIXME why unwrap?
46+
let idx = seg.apply_on_schema_node(&schema.types, cursor.0).unwrap();
47+
let next = TypeKeyEx(idx, next_dkey);
48+
if next == xkey {
49+
return true;
50+
}
51+
cursor = next;
52+
}
53+
54+
false
55+
}
56+
57+
RP::Output(p) => {
58+
let owner = p.owner.upgrade().expect("no strong pointer for type");
59+
let out_ty = match &schema.types[owner.base.key.0 as usize] {
60+
tg_schema::TypeNode::Function { data, .. } => data.output,
61+
_ => unreachable!("expected a function node"),
62+
};
63+
64+
let xkey = TypeKeyEx(ty.idx(), self.gen_from_type(ty));
65+
66+
let mut cursor = TypeKeyEx(
67+
out_ty,
68+
self.gen_from_rpath(&RelativePath::output(Arc::downgrade(&owner), vec![])),
69+
);
70+
for seg in &p.path {
71+
let next_dkey = self.apply_path_segment(&cursor.1, seg);
72+
let idx = seg.apply_on_schema_node(&schema.types, cursor.0).unwrap();
73+
let next = TypeKeyEx(idx, next_dkey);
74+
if next == xkey {
75+
return true;
76+
}
77+
cursor = next;
78+
}
979

10-
#[derive(Default, Debug, PartialEq, Eq, Hash)]
11-
pub struct DuplicationKey {
12-
pub injection: Option<InjectionNode>,
80+
false
81+
}
82+
}
83+
}
1384
}
1485

15-
impl DuplicationKey {
16-
fn new(ty: &Type) -> Self {
17-
Self {
18-
injection: ty.injection().cloned(),
86+
#[derive(Default, Clone, Debug, PartialEq, Eq, Hash)]
87+
pub struct DefaultDuplicationKey {
88+
pub injection: Option<Arc<InjectionNode>>,
89+
}
90+
91+
#[derive(Clone, Debug)]
92+
pub struct DefaultDuplicationKeyGenerator;
93+
94+
impl DuplicationKeyGenerator for DefaultDuplicationKeyGenerator {
95+
type Key = DefaultDuplicationKey;
96+
97+
fn gen_from_rpath(&self, rpath: &RelativePath) -> Self::Key {
98+
Self::Key {
99+
injection: rpath.get_injection(),
19100
}
20101
}
21102

22-
pub fn from_rpath(schema: &tg_schema::Typegraph, rpath: &RelativePath) -> Self {
23-
Self {
24-
injection: rpath.get_injection(schema),
103+
fn gen_from_type(&self, ty: &Type) -> Self::Key {
104+
Self::Key {
105+
injection: ty.injection(),
25106
}
26107
}
27108

28-
pub fn is_empty(&self) -> bool {
109+
fn apply_path_segment(&self, key: &Self::Key, path_seg: &PathSegment) -> Self::Key {
110+
let inj = key
111+
.injection
112+
.as_ref()
113+
.and_then(|inj| path_seg.apply_on_injection(inj));
114+
Self::Key { injection: inj }
115+
}
116+
}
117+
impl DupKey for DefaultDuplicationKey {
118+
fn is_default(&self) -> bool {
29119
self.injection
30120
.as_ref()
31121
.map(|inj| inj.is_empty())
32122
.unwrap_or(true)
33123
}
34124
}
35125

36-
impl From<&Type> for DuplicationKey {
37-
fn from(ty: &Type) -> Self {
38-
Self::new(ty)
39-
}
40-
}
41-
42126
pub enum Deduplication {
43127
/// a previously registered type was found
44128
Reuse(Type),
@@ -55,12 +139,15 @@ impl Deduplication {
55139
}
56140
}
57141

58-
impl ConversionMap {
59-
pub fn deduplicate(&self, type_idx: u32, dkey: &DuplicationKey) -> Result<Deduplication> {
142+
impl<DKG: DuplicationKeyGenerator> ConversionMap<DKG> {
143+
pub fn deduplicate(&self, type_idx: u32, dkey: &DKG::Key) -> Result<Deduplication>
144+
where
145+
DKG: DuplicationKeyGenerator,
146+
{
60147
match self.direct.get(type_idx as usize) {
61148
Some(MapItem::Unset) => Ok(Deduplication::register(
62149
type_idx,
63-
match dkey.is_empty() {
150+
match dkey.is_default() {
64151
true => 0,
65152
// Duplication key will always be empty for functions and namespaces;
66153
// hence, this will always be valid.
@@ -72,7 +159,7 @@ impl ConversionMap {
72159
}
73160
Some(MapItem::Function(fn_ty)) => Ok(Deduplication::reuse(fn_ty.wrap())),
74161
Some(MapItem::Value(value_type)) => {
75-
if dkey.is_empty() {
162+
if dkey.is_default() {
76163
if let Some(item) = value_type.default.as_ref() {
77164
Ok(Deduplication::reuse(item.ty.clone()))
78165
} else {

src/typegraph/graph/src/conv/key.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
// Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0.
22
// SPDX-License-Identifier: MPL-2.0
33

4-
use crate::{Type, TypeNodeExt as _};
5-
6-
use super::dedup::DuplicationKey;
4+
use super::dedup::DupKey;
75

86
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
97
pub struct TypeKey(pub u32, pub u32); // Type idx and an variant id (duplicate id)
@@ -15,10 +13,4 @@ impl std::fmt::Debug for TypeKey {
1513
}
1614

1715
#[derive(Debug, PartialEq)]
18-
pub struct TypeKeyEx(pub u32, pub DuplicationKey);
19-
20-
impl From<&Type> for TypeKeyEx {
21-
fn from(ty: &Type) -> Self {
22-
Self(ty.idx(), From::from(ty))
23-
}
24-
}
16+
pub struct TypeKeyEx<K: DupKey>(pub u32, pub K);

src/typegraph/graph/src/conv/map.rs

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::path::ValueTypePath;
88
use crate::{Arc, FunctionType, ObjectType, Type, TypeNodeExt as _};
99
use std::collections::HashMap;
1010

11-
use super::dedup::DuplicationKey;
11+
use super::dedup::{DupKey, DuplicationKeyGenerator};
1212
use super::{RelativePath, TypeKey};
1313

1414
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
@@ -24,13 +24,13 @@ pub struct MapValueItem {
2424
}
2525

2626
#[derive(Debug)]
27-
pub struct ValueType {
27+
pub struct ValueType<K: DupKey> {
2828
pub default: Option<MapValueItem>,
2929
// duplication
30-
pub variants: IndexMap<DuplicationKey, MapValueItem>,
30+
pub variants: IndexMap<K, MapValueItem>,
3131
}
3232

33-
impl ValueType {
33+
impl<K: DupKey> ValueType<K> {
3434
pub fn get(&self, variant_idx: u32) -> Option<&MapValueItem> {
3535
let variant_idx = variant_idx as usize;
3636
if variant_idx == 0 {
@@ -59,15 +59,15 @@ impl ValueType {
5959
}
6060

6161
#[derive(Debug)]
62-
pub enum MapItem {
62+
pub enum MapItem<K: DupKey> {
6363
Unset,
6464
Namespace(Arc<ObjectType>, Vec<Arc<str>>),
6565
Function(Arc<FunctionType>),
66-
Value(ValueType),
66+
Value(ValueType<K>),
6767
}
6868

69-
impl MapItem {
70-
pub fn as_value(&self) -> Option<&ValueType> {
69+
impl<K: DupKey> MapItem<K> {
70+
pub fn as_value(&self) -> Option<&ValueType<K>> {
7171
match self {
7272
Self::Value(v) => Some(v),
7373
_ => None,
@@ -76,17 +76,19 @@ impl MapItem {
7676
}
7777

7878
#[derive(Debug)]
79-
pub struct ConversionMap {
80-
pub direct: Vec<MapItem>,
79+
pub struct ConversionMap<G: DuplicationKeyGenerator> {
80+
dup_key_gen: G,
81+
pub direct: Vec<MapItem<G::Key>>,
8182
pub reverse: HashMap<RelativePath, TypeKey>,
8283
}
8384

84-
impl ConversionMap {
85-
pub fn new(schema: &tg_schema::Typegraph) -> Self {
85+
impl<G: DuplicationKeyGenerator> ConversionMap<G> {
86+
pub fn new(schema: &tg_schema::Typegraph, dup_key_gen: &G) -> Self {
8687
let type_count = schema.types.len();
8788
let mut direct = Vec::with_capacity(type_count);
8889
direct.resize_with(type_count, || MapItem::Unset);
8990
Self {
91+
dup_key_gen: dup_key_gen.clone(),
9092
direct,
9193
reverse: Default::default(),
9294
}
@@ -120,7 +122,7 @@ impl ConversionMap {
120122
}
121123
}
122124

123-
impl ConversionMap {
125+
impl<G: DuplicationKeyGenerator> ConversionMap<G> {
124126
pub fn register(&mut self, rpath: RelativePath, node: Type) -> Result<()> {
125127
let key = node.key();
126128
let item = std::mem::replace(&mut self.direct[key.0 as usize], MapItem::Unset);
@@ -131,8 +133,8 @@ impl ConversionMap {
131133
MapItem::Namespace(node.assert_object()?.clone(), path.clone())
132134
}
133135
RelativePath::Input(_) => {
134-
let dkey = DuplicationKey::from(&node);
135-
if dkey.is_empty() || !node.is_composite() {
136+
let dkey = self.dup_key_gen.gen_from_type(&node);
137+
if dkey.is_default() || !node.is_composite() {
136138
MapItem::Value(ValueType {
137139
default: Some(MapValueItem {
138140
ty: node.clone(),
@@ -182,9 +184,9 @@ impl ConversionMap {
182184
.clone()
183185
.try_into()
184186
.map_err(|e| eyre!("relative path is not a value type: {:?}", e))?;
185-
let dkey = DuplicationKey::from(&node);
187+
let dkey = self.dup_key_gen.gen_from_type(&node);
186188
if key.1 == 0 {
187-
debug_assert!(dkey.is_empty());
189+
debug_assert!(dkey.is_default());
188190
if value_type.default.is_some() {
189191
bail!("duplicate default value type: {:?}", key);
190192
}
@@ -193,7 +195,7 @@ impl ConversionMap {
193195
relative_paths: std::iter::once(rpath).collect(),
194196
});
195197
} else {
196-
debug_assert!(!dkey.is_empty());
198+
debug_assert!(!dkey.is_default());
197199
let index = key.1 - 1;
198200
if index != value_type.variants.len() as u32 {
199201
bail!("unexpected ordinal number for type registration: {:?}", key);

0 commit comments

Comments
 (0)