From 3070439c00d1f6c105b4b9cf6ca655892ec18571 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 8 Jul 2011 11:29:56 -0700 Subject: [PATCH] Encode/decode a crate's externel dependencies. Issue #632 The encoding is very simple right now, just the crate name. Ultimately this won't be enough for our versioning needs, but it should fill our immediate need of being able to correlate encoded crate numbers to actual crates. --- src/comp/metadata/common.rs | 6 +++++ src/comp/metadata/decoder.rs | 29 ++++++++++++++++++++++- src/comp/metadata/encoder.rs | 46 ++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/src/comp/metadata/common.rs b/src/comp/metadata/common.rs index 5393e1d0b7ed..58db989cba30 100644 --- a/src/comp/metadata/common.rs +++ b/src/comp/metadata/common.rs @@ -56,6 +56,12 @@ const uint tag_meta_item_word = 0x23u; const uint tag_meta_item_list = 0x24u; +// The list of crates that this crate depends on +const uint tag_crate_deps = 0x25u; + +// A single crate dependency +const uint tag_crate_dep = 0x26u; + // djb's cdb hashes. fn hash_node_id(&int node_id) -> uint { ret 177573u ^ (node_id as uint); } diff --git a/src/comp/metadata/decoder.rs b/src/comp/metadata/decoder.rs index 30d016b2cf17..8aab0e739fcf 100644 --- a/src/comp/metadata/decoder.rs +++ b/src/comp/metadata/decoder.rs @@ -327,7 +327,7 @@ fn list_meta_items(&ebml::doc meta_items, io::writer out) { } fn list_crate_attributes(&ebml::doc md, io::writer out) { - out.write_str("=Crate="); + out.write_str("=Crate Attributes="); for (ast::attribute attr in get_attributes(md)) { out.write_str(#fmt("%s", pprust::attribute_to_str(attr))); @@ -340,6 +340,32 @@ fn get_crate_attributes(&vec[u8] data) -> ast::attribute[] { ret get_attributes(ebml::new_doc(data)); } +type crate_dep = tup(ast::crate_num, str); + +fn get_crate_deps(&vec[u8] data) -> vec[crate_dep] { + let vec[crate_dep] deps = []; + auto cratedoc = ebml::new_doc(data); + auto depsdoc = ebml::get_doc(cratedoc, tag_crate_deps); + auto crate_num = 1; + for each (ebml::doc depdoc in + ebml::tagged_docs(depsdoc, tag_crate_dep)) { + auto depname = str::unsafe_from_bytes(ebml::doc_data(depdoc)); + deps += [tup(crate_num, depname)]; + crate_num += 1; + } + ret deps; +} + +fn list_crate_deps(&vec[u8] data, io::writer out) { + out.write_str("=External Dependencies=\n"); + + for (crate_dep dep in get_crate_deps(data)) { + out.write_str(#fmt("%d %s\n", dep._0, dep._1)); + } + + out.write_str("\n"); +} + fn list_crate_items(vec[u8] bytes, &ebml::doc md, io::writer out) { out.write_str("=Items=\n"); auto paths = ebml::get_doc(md, tag_paths); @@ -364,6 +390,7 @@ fn list_crate_items(vec[u8] bytes, &ebml::doc md, io::writer out) { fn list_crate_metadata(vec[u8] bytes, io::writer out) { auto md = ebml::new_doc(bytes); list_crate_attributes(md, out); + list_crate_deps(bytes, out); list_crate_items(bytes, md, out); } diff --git a/src/comp/metadata/encoder.rs b/src/comp/metadata/encoder.rs index 53af9b00dbc1..89634d233bff 100644 --- a/src/comp/metadata/encoder.rs +++ b/src/comp/metadata/encoder.rs @@ -520,6 +520,49 @@ fn synthesize_crate_attrs(&@encode_ctxt ecx, ret attrs; } +fn encode_crate_deps(&ebml::writer ebml_w, &cstore::cstore cstore) { + + fn get_ordered_names(&cstore::cstore cstore) -> vec[str] { + type hashkv = @tup(crate_num, cstore::crate_metadata); + type numname = tup(crate_num, str); + + // Pull the cnums and names out of cstore + let vec[mutable numname] pairs = [mutable]; + for each (hashkv hashkv in cstore.metas.items()) { + pairs += [mutable tup(hashkv._0, hashkv._1.name)]; + } + + // Sort by cnum + fn lteq(&numname kv1, &numname kv2) -> bool { kv1._0 <= kv2._0 } + std::sort::quick_sort(lteq, pairs); + + // Sanity-check the crate numbers + auto expected_cnum = 1; + for (numname n in pairs) { + assert n._0 == expected_cnum; + expected_cnum += 1; + } + + // Return just the names + fn name(&numname kv) -> str { kv._1 } + // mutable -> immutable hack for vec::map + auto immpairs = vec::slice(pairs, 0u, vec::len(pairs)); + ret vec::map(name, immpairs); + } + + // We're just going to write a list of crate names, with the assumption + // that they are numbered 1 to n. + // FIXME: This is not nearly enough to support correct versioning + // but is enough to get transitive crate dependencies working. + ebml::start_tag(ebml_w, tag_crate_deps); + for (str cname in get_ordered_names(cstore)) { + ebml::start_tag(ebml_w, tag_crate_dep); + ebml_w.writer.write(str::bytes(cname)); + ebml::end_tag(ebml_w); + } + ebml::end_tag(ebml_w); +} + fn encode_metadata(&@crate_ctxt cx, &@crate crate) -> str { auto abbrevs = map::mk_hashmap(ty::hash_ty, ty::eq_ty); @@ -531,6 +574,9 @@ fn encode_metadata(&@crate_ctxt cx, &@crate crate) -> str { auto crate_attrs = synthesize_crate_attrs(ecx, crate); encode_attributes(ebml_w, crate_attrs); + + encode_crate_deps(ebml_w, cx.sess.get_cstore()); + // Encode and index the paths. ebml::start_tag(ebml_w, tag_paths);