DEPS_syntax := std term serialize log fmt_macros arena libc rustc_bitflags
-DEPS_rustc := syntax flate arena serialize getopts rustc_front\
+DEPS_rustc := syntax flate arena serialize getopts rbml rustc_front\
log graphviz rustc_llvm rustc_back rustc_data_structures
DEPS_rustc_back := std syntax rustc_llvm rustc_front flate log libc
DEPS_rustc_borrowck := rustc rustc_front log graphviz syntax
self.pos = old_pos;
Ok(result)
}
+
+ pub fn position(&self) -> usize {
+ self.pos
+ }
+
+ pub fn advance(&mut self, bytes: usize) {
+ self.pos += bytes;
+ }
}
impl<'doc> serialize::Decoder for Decoder<'doc> {
extern crate getopts;
extern crate graphviz;
extern crate libc;
+extern crate rbml;
extern crate rustc_llvm;
extern crate rustc_back;
extern crate rustc_front;
krate: &hir::Crate) -> Vec<u8> { vec![] }
fn metadata_encoding_version(&self) -> &[u8] { unimplemented!() }
}
+
+
+/// Metadata encoding and decoding can make use of thread-local encoding and
+/// decoding contexts. These allow implementers of serialize::Encodable and
+/// Decodable to access information and datastructures that would otherwise not
+/// be available to them. For example, we can automatically translate def-id and
+/// span information during decoding because the decoding context knows which
+/// crate the data is decoded from. Or it allows to make ty::Ty decodable
+/// because the context has access to the ty::ctxt that is needed for creating
+/// ty::Ty instances.
+///
+/// Note, however, that this only works for RBML-based encoding and decoding at
+/// the moment.
+pub mod tls {
+ use rbml::writer::Encoder as RbmlEncoder;
+ use rbml::reader::Decoder as RbmlDecoder;
+ use serialize;
+ use std::mem;
+ use middle::ty::{self, Ty};
+ use middle::subst::Substs;
+ use middle::def_id::DefId;
+
+ pub trait EncodingContext<'tcx> {
+ fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
+ fn encode_ty(&self, rbml_w: &mut RbmlEncoder, t: Ty<'tcx>);
+ fn encode_substs(&self, rbml_w: &mut RbmlEncoder, substs: &Substs<'tcx>);
+ }
+
+ /// Marker type used for the scoped TLS slot.
+ /// The type context cannot be used directly because the scoped TLS
+ /// in libstd doesn't allow types generic over lifetimes.
+ struct TlsPayload;
+
+ scoped_thread_local!(static TLS_ENCODING: TlsPayload);
+
+ /// Execute f after pushing the given EncodingContext onto the TLS stack.
+ pub fn enter_encoding_context<'tcx, F, R>(ecx: &EncodingContext<'tcx>,
+ rbml_w: &mut RbmlEncoder,
+ f: F) -> R
+ where F: FnOnce(&EncodingContext<'tcx>, &mut RbmlEncoder) -> R
+ {
+ let tls_payload = (ecx as *const _, rbml_w as *mut _);
+ let tls_ptr = &tls_payload as *const _ as *const TlsPayload;
+ TLS_ENCODING.set(unsafe { &*tls_ptr }, || f(ecx, rbml_w))
+ }
+
+ /// Execute f with access to the thread-local encoding context and
+ /// rbml encoder. This function will panic if the encoder passed in and the
+ /// context encoder are not the same.
+ ///
+ /// Note that this method is 'practically' safe due to its checking that the
+ /// encoder passed in is the same as the one in TLS, but it would still be
+ /// possible to construct cases where the EncodingContext is exchanged
+ /// while the same encoder is used, thus working with a wrong context.
+ pub fn with_encoding_context<'tcx, E, F, R>(encoder: &mut E, f: F) -> R
+ where F: FnOnce(&EncodingContext<'tcx>, &mut RbmlEncoder) -> R,
+ E: serialize::Encoder
+ {
+ unsafe {
+ unsafe_with_encoding_context(|ecx, rbml_w| {
+ assert!(encoder as *mut _ as usize == rbml_w as *mut _ as usize);
+
+ let ecx: &EncodingContext<'tcx> = mem::transmute(ecx);
+
+ f(ecx, rbml_w)
+ })
+ }
+ }
+
+ /// Execute f with access to the thread-local encoding context and
+ /// rbml encoder.
+ pub unsafe fn unsafe_with_encoding_context<F, R>(f: F) -> R
+ where F: FnOnce(&EncodingContext, &mut RbmlEncoder) -> R
+ {
+ TLS_ENCODING.with(|tls| {
+ let tls_payload = (tls as *const TlsPayload)
+ as *mut (&EncodingContext, &mut RbmlEncoder);
+ f((*tls_payload).0, (*tls_payload).1)
+ })
+ }
+
+ pub trait DecodingContext<'tcx> {
+ fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
+ fn decode_ty(&self, rbml_r: &mut RbmlDecoder) -> ty::Ty<'tcx>;
+ fn decode_substs(&self, rbml_r: &mut RbmlDecoder) -> Substs<'tcx>;
+ fn translate_def_id(&self, def_id: DefId) -> DefId;
+ }
+
+ scoped_thread_local!(static TLS_DECODING: TlsPayload);
+
+ /// Execute f after pushing the given DecodingContext onto the TLS stack.
+ pub fn enter_decoding_context<'tcx, F, R>(dcx: &DecodingContext<'tcx>,
+ rbml_r: &mut RbmlDecoder,
+ f: F) -> R
+ where F: FnOnce(&DecodingContext<'tcx>, &mut RbmlDecoder) -> R
+ {
+ let tls_payload = (dcx as *const _, rbml_r as *mut _);
+ let tls_ptr = &tls_payload as *const _ as *const TlsPayload;
+ TLS_DECODING.set(unsafe { &*tls_ptr }, || f(dcx, rbml_r))
+ }
+
+ /// Execute f with access to the thread-local decoding context and
+ /// rbml decoder. This function will panic if the decoder passed in and the
+ /// context decoder are not the same.
+ ///
+ /// Note that this method is 'practically' safe due to its checking that the
+ /// decoder passed in is the same as the one in TLS, but it would still be
+ /// possible to construct cases where the DecodingContext is exchanged
+ /// while the same decoder is used, thus working with a wrong context.
+ pub fn with_decoding_context<'decoder, 'tcx, D, F, R>(d: &'decoder mut D, f: F) -> R
+ where D: serialize::Decoder,
+ F: FnOnce(&DecodingContext<'tcx>,
+ &mut RbmlDecoder) -> R,
+ 'tcx: 'decoder
+ {
+ unsafe {
+ unsafe_with_decoding_context(|dcx, rbml_r| {
+ assert!((d as *mut _ as usize) == (rbml_r as *mut _ as usize));
+
+ let dcx: &DecodingContext<'tcx> = mem::transmute(dcx);
+
+ f(dcx, rbml_r)
+ })
+ }
+ }
+
+ /// Execute f with access to the thread-local decoding context and
+ /// rbml decoder.
+ pub unsafe fn unsafe_with_decoding_context<F, R>(f: F) -> R
+ where F: FnOnce(&DecodingContext, &mut RbmlDecoder) -> R
+ {
+ TLS_DECODING.with(|tls| {
+ let tls_payload = (tls as *const TlsPayload)
+ as *mut (&DecodingContext, &mut RbmlDecoder);
+ f((*tls_payload).0, (*tls_payload).1)
+ })
+ }
+}
pub use self::ParamSpace::*;
pub use self::RegionSubsts::*;
+use middle::cstore;
use middle::ty::{self, Ty, HasTypeFlags, RegionEscape};
use middle::ty::fold::{TypeFoldable, TypeFolder};
+use serialize::{Encodable, Encoder, Decodable, Decoder};
use std::fmt;
use std::iter::IntoIterator;
use std::slice::Iter;
}
}
+impl<'tcx> Encodable for Substs<'tcx> {
+
+ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+ cstore::tls::with_encoding_context(s, |ecx, rbml_w| {
+ ecx.encode_substs(rbml_w, self);
+ Ok(())
+ })
+ }
+}
+
+impl<'tcx> Decodable for Substs<'tcx> {
+ fn decode<D: Decoder>(d: &mut D) -> Result<Substs<'tcx>, D::Error> {
+ cstore::tls::with_decoding_context(d, |dcx, rbml_r| {
+ Ok(dcx.decode_substs(rbml_r))
+ })
+ }
+}
+
+impl<'tcx> Decodable for &'tcx Substs<'tcx> {
+ fn decode<D: Decoder>(d: &mut D) -> Result<&'tcx Substs<'tcx>, D::Error> {
+ let substs = cstore::tls::with_decoding_context(d, |dcx, rbml_r| {
+ let substs = dcx.decode_substs(rbml_r);
+ dcx.tcx().mk_substs(substs)
+ });
+
+ Ok(substs)
+ }
+}
+
impl RegionSubsts {
pub fn map<F>(self, op: F) -> RegionSubsts where
F: FnOnce(VecPerParamSpace<ty::Region>) -> VecPerParamSpace<ty::Region>,
use front::map as ast_map;
use front::map::LinkedPath;
use middle;
-use middle::cstore::{CrateStore, LOCAL_CRATE};
+use middle::cstore::{self, CrateStore, LOCAL_CRATE};
use middle::def::{self, ExportMap};
use middle::def_id::DefId;
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
use util::nodemap::{NodeMap, NodeSet, DefIdMap};
use util::nodemap::FnvHashMap;
+use serialize::{Encodable, Encoder, Decodable, Decoder};
use std::borrow::{Borrow, Cow};
use std::cell::{Cell, RefCell};
use std::hash::{Hash, Hasher};
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
+impl<'tcx> Encodable for Ty<'tcx> {
+ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+ cstore::tls::with_encoding_context(s, |ecx, rbml_w| {
+ ecx.encode_ty(rbml_w, *self);
+ Ok(())
+ })
+ }
+}
+
+impl<'tcx> Decodable for Ty<'tcx> {
+ fn decode<D: Decoder>(d: &mut D) -> Result<Ty<'tcx>, D::Error> {
+ cstore::tls::with_decoding_context(d, |dcx, rbml_r| {
+ Ok(dcx.decode_ty(rbml_r))
+ })
+ }
+}
+
+
/// Upvars do not get their own node-id. Instead, we use the pair of
/// the original var id (that is, the root variable that is referenced
/// by the upvar) and the id of the closure expression.
}
}
+impl<'tcx> Encodable for AdtDef<'tcx> {
+ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+ self.did.encode(s)
+ }
+}
+
+impl<'tcx> Decodable for AdtDef<'tcx> {
+ fn decode<D: Decoder>(d: &mut D) -> Result<AdtDef<'tcx>, D::Error> {
+ let def_id: DefId = try!{ Decodable::decode(d) };
+
+ cstore::tls::with_decoding_context(d, |dcx, _| {
+ let def_id = dcx.translate_def_id(def_id);
+ Ok(dcx.tcx().lookup_adt_def(def_id))
+ })
+ }
+}
+
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum AdtKind { Struct, Enum }
use syntax::{ast, ast_util, codemap};
use syntax::ast::NodeIdAssigner;
-use syntax::codemap::Span;
use syntax::ptr::P;
use std::cell::Cell;
fn new_def_id(&self, def_id: DefId) -> DefId {
self.tr_def_id(def_id)
}
- fn new_span(&self, span: Span) -> Span {
+ fn new_span(&self, span: codemap::Span) -> codemap::Span {
self.tr_span(span)
}
}
}
/// Translates a `Span` from an extern crate to the corresponding `Span`
- /// within the local crate's codemap. `creader::import_codemap()` will
- /// already have allocated any additionally needed FileMaps in the local
- /// codemap as a side-effect of creating the crate_metadata's
- /// `codemap_import_info`.
- pub fn tr_span(&self, span: Span) -> Span {
- let span = if span.lo > span.hi {
- // Currently macro expansion sometimes produces invalid Span values
- // where lo > hi. In order not to crash the compiler when trying to
- // translate these values, let's transform them into something we
- // can handle (and which will produce useful debug locations at
- // least some of the time).
- // This workaround is only necessary as long as macro expansion is
- // not fixed. FIXME(#23480)
- codemap::mk_sp(span.lo, span.lo)
- } else {
- span
- };
-
- let imported_filemaps = self.cdata.imported_filemaps(self.tcx.sess.codemap());
- let filemap = {
- // Optimize for the case that most spans within a translated item
- // originate from the same filemap.
- let last_filemap_index = self.last_filemap_index.get();
- let last_filemap = &imported_filemaps[last_filemap_index];
-
- if span.lo >= last_filemap.original_start_pos &&
- span.lo <= last_filemap.original_end_pos &&
- span.hi >= last_filemap.original_start_pos &&
- span.hi <= last_filemap.original_end_pos {
- last_filemap
- } else {
- let mut a = 0;
- let mut b = imported_filemaps.len();
-
- while b - a > 1 {
- let m = (a + b) / 2;
- if imported_filemaps[m].original_start_pos > span.lo {
- b = m;
- } else {
- a = m;
- }
- }
-
- self.last_filemap_index.set(a);
- &imported_filemaps[a]
- }
- };
-
- let lo = (span.lo - filemap.original_start_pos) +
- filemap.translated_filemap.start_pos;
- let hi = (span.hi - filemap.original_start_pos) +
- filemap.translated_filemap.start_pos;
-
- codemap::mk_sp(lo, hi)
+ /// within the local crate's codemap.
+ pub fn tr_span(&self, span: codemap::Span) -> codemap::Span {
+ decoder::translate_span(self.cdata,
+ self.tcx.sess.codemap(),
+ &self.last_filemap_index,
+ span)
}
}
}
}
-impl tr for Span {
- fn tr(&self, dcx: &DecodeContext) -> Span {
+impl tr for codemap::Span {
+ fn tr(&self, dcx: &DecodeContext) -> codemap::Span {
dcx.tr_span(*self)
}
}
None
}
+/// Translates a `Span` from an extern crate to the corresponding `Span`
+/// within the local crate's codemap.
+pub fn translate_span(cdata: Cmd,
+ codemap: &codemap::CodeMap,
+ last_filemap_index_hint: &Cell<usize>,
+ span: codemap::Span)
+ -> codemap::Span {
+ let span = if span.lo > span.hi {
+ // Currently macro expansion sometimes produces invalid Span values
+ // where lo > hi. In order not to crash the compiler when trying to
+ // translate these values, let's transform them into something we
+ // can handle (and which will produce useful debug locations at
+ // least some of the time).
+ // This workaround is only necessary as long as macro expansion is
+ // not fixed. FIXME(#23480)
+ codemap::mk_sp(span.lo, span.lo)
+ } else {
+ span
+ };
+
+ let imported_filemaps = cdata.imported_filemaps(&codemap);
+ let filemap = {
+ // Optimize for the case that most spans within a translated item
+ // originate from the same filemap.
+ let last_filemap_index = last_filemap_index_hint.get();
+ let last_filemap = &imported_filemaps[last_filemap_index];
+
+ if span.lo >= last_filemap.original_start_pos &&
+ span.lo <= last_filemap.original_end_pos &&
+ span.hi >= last_filemap.original_start_pos &&
+ span.hi <= last_filemap.original_end_pos {
+ last_filemap
+ } else {
+ let mut a = 0;
+ let mut b = imported_filemaps.len();
+
+ while b - a > 1 {
+ let m = (a + b) / 2;
+ if imported_filemaps[m].original_start_pos > span.lo {
+ b = m;
+ } else {
+ a = m;
+ }
+ }
+
+ last_filemap_index_hint.set(a);
+ &imported_filemaps[a]
+ }
+ };
+
+ let lo = (span.lo - filemap.original_start_pos) +
+ filemap.translated_filemap.start_pos;
+ let hi = (span.hi - filemap.original_start_pos) +
+ filemap.translated_filemap.start_pos;
+
+ codemap::mk_sp(lo, hi)
+}
+
pub fn each_inherent_implementation_for_type<F>(cdata: Cmd,
id: DefIndex,
mut callback: F)
use tyencode;
use index::{self, IndexData};
-use middle::cstore::{LOCAL_CRATE, CrateStore, InlinedItemRef, LinkMeta};
+use middle::cstore::{LOCAL_CRATE, CrateStore, InlinedItemRef, LinkMeta, tls};
use middle::def;
use middle::def_id::{CRATE_DEF_INDEX, DefId};
use middle::dependency_format::Linkage;
pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2 ];
pub fn encode_metadata(parms: EncodeParams, krate: &hir::Crate) -> Vec<u8> {
+ let EncodeParams {
+ item_symbols,
+ diag,
+ tcx,
+ reexports,
+ cstore,
+ encode_inlined_item,
+ link_meta,
+ reachable,
+ ..
+ } = parms;
+ let ecx = EncodeContext {
+ diag: diag,
+ tcx: tcx,
+ reexports: reexports,
+ item_symbols: item_symbols,
+ link_meta: link_meta,
+ cstore: cstore,
+ encode_inlined_item: RefCell::new(encode_inlined_item),
+ type_abbrevs: RefCell::new(FnvHashMap()),
+ reachable: reachable,
+ };
+
let mut wr = Cursor::new(Vec::new());
- encode_metadata_inner(&mut wr, parms, krate);
+
+ {
+ let mut rbml_w = Encoder::new(&mut wr);
+ tls::enter_encoding_context(&ecx, &mut rbml_w, |_, rbml_w| {
+ encode_metadata_inner(rbml_w, &ecx, krate)
+ });
+ }
// RBML compacts the encoded bytes whenever appropriate,
// so there are some garbages left after the end of the data.
return v;
}
-fn encode_metadata_inner(wr: &mut Cursor<Vec<u8>>,
- parms: EncodeParams,
+fn encode_metadata_inner(rbml_w: &mut Encoder,
+ ecx: &EncodeContext,
krate: &hir::Crate) {
struct Stats {
attr_bytes: u64,
zero_bytes: 0,
total_bytes: 0,
};
- let EncodeParams {
- item_symbols,
- diag,
- tcx,
- reexports,
- cstore,
- encode_inlined_item,
- link_meta,
- reachable,
- ..
- } = parms;
- let ecx = EncodeContext {
- diag: diag,
- tcx: tcx,
- reexports: reexports,
- item_symbols: item_symbols,
- link_meta: link_meta,
- cstore: cstore,
- encode_inlined_item: RefCell::new(encode_inlined_item),
- type_abbrevs: RefCell::new(FnvHashMap()),
- reachable: reachable,
- };
-
- let mut rbml_w = Encoder::new(wr);
- encode_rustc_version(&mut rbml_w);
- encode_crate_name(&mut rbml_w, &ecx.link_meta.crate_name);
- encode_crate_triple(&mut rbml_w, &tcx.sess.opts.target_triple);
- encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash);
- encode_dylib_dependency_formats(&mut rbml_w, &ecx);
+ encode_rustc_version(rbml_w);
+ encode_crate_name(rbml_w, &ecx.link_meta.crate_name);
+ encode_crate_triple(rbml_w, &ecx.tcx.sess.opts.target_triple);
+ encode_hash(rbml_w, &ecx.link_meta.crate_hash);
+ encode_dylib_dependency_formats(rbml_w, &ecx);
let mut i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
- encode_attributes(&mut rbml_w, &krate.attrs);
+ encode_attributes(rbml_w, &krate.attrs);
stats.attr_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
- encode_crate_deps(&mut rbml_w, ecx.cstore);
+ encode_crate_deps(rbml_w, ecx.cstore);
stats.dep_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
// Encode the language items.
i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
- encode_lang_items(&ecx, &mut rbml_w);
+ encode_lang_items(&ecx, rbml_w);
stats.lang_item_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
// Encode the native libraries used
i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
- encode_native_libraries(&ecx, &mut rbml_w);
+ encode_native_libraries(&ecx, rbml_w);
stats.native_lib_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
// Encode the plugin registrar function
i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
- encode_plugin_registrar_fn(&ecx, &mut rbml_w);
+ encode_plugin_registrar_fn(&ecx, rbml_w);
stats.plugin_registrar_fn_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
// Encode codemap
i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
- encode_codemap(&ecx, &mut rbml_w);
+ encode_codemap(&ecx, rbml_w);
stats.codemap_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
// Encode macro definitions
i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
- encode_macro_defs(&mut rbml_w, krate);
+ encode_macro_defs(rbml_w, krate);
stats.macro_defs_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
// Encode the def IDs of impls, for coherence checking.
i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
- encode_impls(&ecx, krate, &mut rbml_w);
+ encode_impls(&ecx, krate, rbml_w);
stats.impl_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
// Encode miscellaneous info.
i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
- encode_misc_info(&ecx, krate, &mut rbml_w);
- encode_reachable(&ecx, &mut rbml_w);
+ encode_misc_info(&ecx, krate, rbml_w);
+ encode_reachable(&ecx, rbml_w);
stats.misc_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
// Encode and index the items.
rbml_w.start_tag(tag_items);
i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
- let index = encode_info_for_items(&ecx, &mut rbml_w);
+ let index = encode_info_for_items(&ecx, rbml_w);
stats.item_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
rbml_w.end_tag();
i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
- encode_item_index(&mut rbml_w, index.items);
+ encode_item_index(rbml_w, index.items);
stats.index_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
- encode_xrefs(&ecx, &mut rbml_w, index.xrefs);
+ encode_xrefs(&ecx, rbml_w, index.xrefs);
stats.xref_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
- encode_struct_field_attrs(&ecx, &mut rbml_w, krate);
+ encode_struct_field_attrs(&ecx, rbml_w, krate);
stats.total_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
- if tcx.sess.meta_stats() {
+ if ecx.tcx.sess.meta_stats() {
for e in rbml_w.writer.get_ref() {
if *e == 0 {
stats.zero_bytes += 1;
pub mod index;
pub mod loader;
pub mod macro_import;
+pub mod tls_context;
--- /dev/null
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This module provides implementations for the thread-local encoding and
+// decoding context traits in rustc::middle::cstore::tls.
+
+use rbml::writer::Encoder as RbmlEncoder;
+use rbml::reader::Decoder as RbmlDecoder;
+use rustc::middle::cstore::tls;
+use rustc::middle::def_id::DefId;
+use rustc::middle::subst::Substs;
+use rustc::middle::ty::{self, Ty};
+
+use decoder::{self, Cmd};
+use encoder;
+use tydecode::TyDecoder;
+use tyencode;
+
+
+impl<'a, 'tcx: 'a> tls::EncodingContext<'tcx> for encoder::EncodeContext<'a, 'tcx> {
+
+ fn tcx<'s>(&'s self) -> &'s ty::ctxt<'tcx> {
+ &self.tcx
+ }
+
+ fn encode_ty(&self, rbml_w: &mut RbmlEncoder, t: ty::Ty<'tcx>) {
+ encoder::write_type(self, rbml_w, t);
+ }
+
+ fn encode_substs(&self, rbml_w: &mut RbmlEncoder, substs: &Substs<'tcx>) {
+ let ty_str_ctxt = &tyencode::ctxt {
+ diag: self.diag,
+ ds: encoder::def_to_string,
+ tcx: self.tcx,
+ abbrevs: &self.type_abbrevs
+ };
+ tyencode::enc_substs(rbml_w, ty_str_ctxt, substs);
+ }
+}
+
+pub struct DecodingContext<'a, 'tcx: 'a> {
+ pub crate_metadata: Cmd<'a>,
+ pub tcx: &'a ty::ctxt<'tcx>,
+}
+
+impl<'a, 'tcx: 'a> tls::DecodingContext<'tcx> for DecodingContext<'a, 'tcx> {
+
+ fn tcx<'s>(&'s self) -> &'s ty::ctxt<'tcx> {
+ &self.tcx
+ }
+
+ fn decode_ty(&self, rbml_r: &mut RbmlDecoder) -> ty::Ty<'tcx> {
+ let def_id_convert = &mut |did| {
+ decoder::translate_def_id(self.crate_metadata, did)
+ };
+
+ let starting_position = rbml_r.position();
+
+ let mut ty_decoder = TyDecoder::new(
+ self.crate_metadata.data.as_slice(),
+ self.crate_metadata.cnum,
+ starting_position,
+ self.tcx,
+ def_id_convert);
+
+ let ty = ty_decoder.parse_ty();
+
+ let end_position = ty_decoder.position();
+
+ // We can just reuse the tydecode implementation for parsing types, but
+ // we have to make sure to leave the rbml reader at the position just
+ // after the type.
+ rbml_r.advance(end_position - starting_position);
+ ty
+ }
+
+ fn decode_substs(&self, rbml_r: &mut RbmlDecoder) -> Substs<'tcx> {
+ let def_id_convert = &mut |did| {
+ decoder::translate_def_id(self.crate_metadata, did)
+ };
+
+ let starting_position = rbml_r.position();
+
+ let mut ty_decoder = TyDecoder::new(
+ self.crate_metadata.data.as_slice(),
+ self.crate_metadata.cnum,
+ starting_position,
+ self.tcx,
+ def_id_convert);
+
+ let substs = ty_decoder.parse_substs();
+
+ let end_position = ty_decoder.position();
+
+ rbml_r.advance(end_position - starting_position);
+ substs
+ }
+
+ fn translate_def_id(&self, def_id: DefId) -> DefId {
+ decoder::translate_def_id(self.crate_metadata, def_id)
+ }
+}
}
}
+ pub fn position(&self) -> usize {
+ self.pos
+ }
+
fn peek(&self) -> char {
self.data[self.pos] as char
}