1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use rustc
::hir
::def_id
::{DefId, DefIndex}
;
13 use std
::io
::{Cursor, Write}
;
17 /// As part of the metadata, we generate an index that stores, for
18 /// each DefIndex, the position of the corresponding RBML document (if
19 /// any). This is just a big `[u32]` slice, where an entry of
20 /// `u32::MAX` indicates that there is no RBML document. This little
21 /// struct just stores the offsets within the metadata of the start
22 /// and end of this slice. These are actually part of an RBML
23 /// document, but for looking things up in the metadata, we just
24 /// discard the RBML positioning and jump directly to the data.
31 /// Given the RBML doc representing the index, save the offests
33 pub fn from_rbml(index
: rbml
::Doc
) -> Index
{
34 Index { data_start: index.start, data_end: index.end }
37 /// Given the metadata, extract out the offset of a particular
38 /// DefIndex (if any).
40 pub fn lookup_item(&self, bytes
: &[u8], def_index
: DefIndex
) -> Option
<u32> {
41 let words
= bytes_to_words(&bytes
[self.data_start
..self.data_end
]);
42 let index
= def_index
.as_usize();
44 debug
!("lookup_item: index={:?} words.len={:?}",
47 let position
= u32::from_be(words
[index
]);
48 if position
== u32::MAX
{
49 debug
!("lookup_item: position=u32::MAX");
52 debug
!("lookup_item: position={:?}", position
);
58 /// While we are generating the metadata, we also track the position
59 /// of each DefIndex. It is not required that all definitions appear
60 /// in the metadata, nor that they are serialized in order, and
61 /// therefore we first allocate the vector here and fill it with
62 /// `u32::MAX`. Whenever an index is visited, we fill in the
63 /// appropriate spot by calling `record_position`. We should never
64 /// visit the same index twice.
65 pub struct IndexData
{
70 pub fn new(max_index
: usize) -> IndexData
{
72 positions
: vec
![u32::MAX
; max_index
]
76 pub fn record(&mut self, def_id
: DefId
, position
: u64) {
77 assert
!(def_id
.is_local());
78 self.record_index(def_id
.index
, position
)
81 pub fn record_index(&mut self, item
: DefIndex
, position
: u64) {
82 let item
= item
.as_usize();
84 assert
!(position
< (u32::MAX
as u64));
85 let position
= position
as u32;
87 assert
!(self.positions
[item
] == u32::MAX
,
88 "recorded position for item {:?} twice, first at {:?} and now at {:?}",
89 item
, self.positions
[item
], position
);
91 self.positions
[item
] = position
;
94 pub fn write_index(&self, buf
: &mut Cursor
<Vec
<u8>>) {
95 for &position
in &self.positions
{
96 write_be_u32(buf
, position
);
101 /// A dense index with integer keys. Different API from IndexData (should
102 /// these be merged?)
103 pub struct DenseIndex
{
109 pub fn lookup(&self, buf
: &[u8], ix
: u32) -> Option
<u32> {
110 let data
= bytes_to_words(&buf
[self.start
..self.end
]);
111 data
.get(ix
as usize).map(|d
| u32::from_be(*d
))
113 pub fn from_buf(buf
: &[u8], start
: usize, end
: usize) -> Self {
114 assert
!((end
-start
)%4 == 0 && start
<= end
&& end
<= buf
.len());
122 pub fn write_dense_index(entries
: Vec
<u32>, buf
: &mut Cursor
<Vec
<u8>>) {
123 let elen
= entries
.len();
124 assert
!(elen
< u32::MAX
as usize);
126 for entry
in entries
{
127 write_be_u32(buf
, entry
);
130 info
!("write_dense_index: {} entries", elen
);
133 fn write_be_u32
<W
: Write
>(w
: &mut W
, u
: u32) {
134 let _
= w
.write_all(&[
142 fn bytes_to_words(b
: &[u8]) -> &[u32] {
143 assert
!(b
.len() % 4 == 0);
144 unsafe { slice::from_raw_parts(b.as_ptr() as *const u32, b.len()/4) }