• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::syntax::map::{Entry, UnorderedMap as Map};
2 use crate::syntax::report::Errors;
3 use crate::syntax::{Api, Struct, Type, Types};
4 
5 enum Mark {
6     Visiting,
7     Visited,
8 }
9 
sort<'a>(cx: &mut Errors, apis: &'a [Api], types: &Types<'a>) -> Vec<&'a Struct>10 pub fn sort<'a>(cx: &mut Errors, apis: &'a [Api], types: &Types<'a>) -> Vec<&'a Struct> {
11     let mut sorted = Vec::new();
12     let ref mut marks = Map::new();
13     for api in apis {
14         if let Api::Struct(strct) = api {
15             let _ = visit(cx, strct, &mut sorted, marks, types);
16         }
17     }
18     sorted
19 }
20 
visit<'a>( cx: &mut Errors, strct: &'a Struct, sorted: &mut Vec<&'a Struct>, marks: &mut Map<*const Struct, Mark>, types: &Types<'a>, ) -> Result<(), ()>21 fn visit<'a>(
22     cx: &mut Errors,
23     strct: &'a Struct,
24     sorted: &mut Vec<&'a Struct>,
25     marks: &mut Map<*const Struct, Mark>,
26     types: &Types<'a>,
27 ) -> Result<(), ()> {
28     match marks.entry(strct) {
29         Entry::Occupied(entry) => match entry.get() {
30             Mark::Visiting => return Err(()), // not a DAG
31             Mark::Visited => return Ok(()),
32         },
33         Entry::Vacant(entry) => {
34             entry.insert(Mark::Visiting);
35         }
36     }
37     let mut result = Ok(());
38     for field in &strct.fields {
39         if let Type::Ident(ident) = &field.ty {
40             if let Some(inner) = types.structs.get(&ident.rust) {
41                 if visit(cx, inner, sorted, marks, types).is_err() {
42                     cx.error(field, "unsupported cyclic data structure");
43                     result = Err(());
44                 }
45             }
46         }
47     }
48     marks.insert(strct, Mark::Visited);
49     sorted.push(strct);
50     result
51 }
52