<commit_before>// Not in interpret to make sure we do not use private implementation details

use std::convert::TryInto;
use std::error::Error;
use std::fmt;
use std::hash::Hash;

use rustc::mir;
use rustc::ty::layout::{self, VariantIdx};
use rustc::ty::{self, TyCtxt};

use syntax::{
    source_map::{Span, DUMMY_SP},
    symbol::Symbol,
};

use crate::interpret::{
    intern_const_alloc_recursive, Allocation, ConstValue, ImmTy, Immediate, InterpCx, OpTy, Scalar,
};

mod error;
mod query;

pub use error::*;
pub use query::*;

/// The `InterpCx` is only meant to be used to do field and index projections into constants for
/// `simd_shuffle` and const patterns in match arms.
///
/// The function containing the `match` that is currently being analyzed may have generic bounds
/// that inform us about the generic bounds of the constant. E.g., using an associated constant
/// of a function's generic parameter will require knowledge about the bounds on the generic
/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
fn mk_eval_cx<'mir, 'tcx>(
    tcx: TyCtxt<'tcx>,
    span: Span,
    param_env: ty::ParamEnv<'tcx>,
    can_access_statics: bool,
) -> CompileTimeEvalContext<'mir, 'tcx> {
    debug!("mk_eval_cx: {:?}", param_env);
    InterpCx::new(
        tcx.at(span),
        param_env,
        CompileTimeInterpreter::new(),
        MemoryExtra { can_access_statics },
    )
}

fn op_to_const<'tcx>(
    ecx: &CompileTimeEvalContext<'_, 'tcx>,
    op: OpTy<'tcx>,
) -> &'tcx ty::Const<'tcx> {
    // We do not have value optimizations for everything.
    // Only scalars and slices, since they are very common.
    // Note that further down we turn scalars of undefined bits back to `ByRef`. These can result
    // from scalar unions that are initialized with one of their zero sized variants. We could
    // instead allow `ConstValue::Scalar` to store `ScalarMaybeUndef`, but that would affect all
    // the usual cases of extracting e.g. a `usize`, without there being a real use case for the
    // `Undef` situation.
    let try_as_immediate = match op.layout.abi {
        layout::Abi::Scalar(..) => true,
        layout::Abi::ScalarPair(..) => match op.layout.ty.kind {
            ty::Ref(_, inner, _) => match inner.kind {
                ty::Slice(elem) => elem == ecx.tcx.types.u8,
                ty::Str => true,
                _ => false,
            },
            _ => false,
        },
        _ => false,
    };
    let immediate = if try_as_immediate {
        Err(ecx.read_immediate(op).expect("normalization works on validated constants"))
    } else {
        // It is guaranteed that any non-slice scalar pair is actually ByRef here.
        // When we come back from raw const eval, we are always by-ref. The only way our op here is
        // by-val is if we are in const_field, i.e., if this is (a field of) something that we
        // "tried to make immediate" before. We wouldn't do that for non-slice scalar pairs or
        // structs containing such.
        op.try_as_mplace()
    };
    let val = match immediate {
        Ok(mplace) => {
            let ptr = mplace.ptr.to_ptr().unwrap();
            let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
            ConstValue::ByRef { alloc, offset: ptr.offset }
        }
        // see comment on `let try_as_immediate` above
        Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x {
            ScalarMaybeUndef::Scalar(s) => ConstValue::Scalar(s),
            ScalarMaybeUndef::Undef => {
                // When coming out of "normal CTFE", we'll always have an `Indirect` operand as
                // argument and we will not need this. The only way we can already have an
                // `Immediate` is when we are called from `const_field`, and that `Immediate`
                // comes from a constant so it can happen have `Undef`, because the indirect
                // memory that was read had undefined bytes.
                let mplace = op.assert_mem_place();
                let ptr = mplace.ptr.to_ptr().unwrap();
                let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
                ConstValue::ByRef { alloc, offset: ptr.offset }
            }
        },
        Err(ImmTy { imm: Immediate::ScalarPair(a, b), .. }) => {
            let (data, start) = match a.not_undef().unwrap() {
                Scalar::Ptr(ptr) => {
                    (ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id), ptr.offset.bytes())
                }
                Scalar::Raw { .. } => (
                    ecx.tcx.intern_const_alloc(Allocation::from_byte_aligned_bytes(b"" as &[u8])),
                    0,
                ),
            };
            let len = b.to_machine_usize(&ecx.tcx.tcx).unwrap();
            let start = start.try_into().unwrap();
            let len: usize = len.try_into().unwrap();
            ConstValue::Slice { data, start, end: start + len }
        }
    };
    ecx.tcx.mk_const(ty::Const { val: ty::ConstKind::Value(val), ty: op.layout.ty })
}

/// Extracts a field of a (variant of a) const.
// this function uses `unwrap` copiously, because an already validated constant must have valid
// fields and can thus never fail outside of compiler bugs
pub fn const_field<'tcx>(
    tcx: TyCtxt<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    variant: Option<VariantIdx>,
    field: mir::Field,
    value: &'tcx ty::Const<'tcx>,
) -> &'tcx ty::Const<'tcx> {
    trace!("const_field: {:?}, {:?}", field, value);
    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
    // get the operand again
    let op = ecx.eval_const_to_op(value, None).unwrap();
    // downcast
    let down = match variant {
        None => op,
        Some(variant) => ecx.operand_downcast(op, variant).unwrap(),
    };
    // then project
    let field = ecx.operand_field(down, field.index() as u64).unwrap();
    // and finally move back to the const world, always normalizing because
    // this is not called for statics.
    op_to_const(&ecx, field)
}

pub fn const_caller_location<'tcx>(
    tcx: TyCtxt<'tcx>,
    (file, line, col): (Symbol, u32, u32),
) -> &'tcx ty::Const<'tcx> {
    trace!("const_caller_location: {}:{}:{}", file, line, col);
    let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false);

    let loc_ty = tcx.caller_location_ty();
    let loc_place = ecx.alloc_caller_location(file, line, col);
    intern_const_alloc_recursive(&mut ecx, None, loc_place).unwrap();
    let loc_const = ty::Const {
        ty: loc_ty,
        val: ty::ConstKind::Value(ConstValue::Scalar(loc_place.ptr.into())),
    };

    tcx.mk_const(loc_const)
}

// this function uses `unwrap` copiously, because an already validated constant must have valid
// fields and can thus never fail outside of compiler bugs
pub fn const_variant_index<'tcx>(
    tcx: TyCtxt<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    val: &'tcx ty::Const<'tcx>,
) -> VariantIdx {
    trace!("const_variant_index: {:?}", val);
    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
    let op = ecx.eval_const_to_op(val, None).unwrap();
    ecx.read_discriminant(op).unwrap().1
}
<commit_msg>Make some functions crate local<commit_after>// Not in interpret to make sure we do not use private implementation details

use std::convert::TryInto;
use std::error::Error;
use std::fmt;
use std::hash::Hash;

use rustc::mir;
use rustc::ty::layout::{self, VariantIdx};
use rustc::ty::{self, TyCtxt};

use syntax::{
    source_map::{Span, DUMMY_SP},
    symbol::Symbol,
};

use crate::interpret::{
    intern_const_alloc_recursive, Allocation, ConstValue, ImmTy, Immediate, InterpCx, OpTy, Scalar,
};

mod error;
mod query;

pub use error::*;
pub use query::*;

/// The `InterpCx` is only meant to be used to do field and index projections into constants for
/// `simd_shuffle` and const patterns in match arms.
///
/// The function containing the `match` that is currently being analyzed may have generic bounds
/// that inform us about the generic bounds of the constant. E.g., using an associated constant
/// of a function's generic parameter will require knowledge about the bounds on the generic
/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
fn mk_eval_cx<'mir, 'tcx>(
    tcx: TyCtxt<'tcx>,
    span: Span,
    param_env: ty::ParamEnv<'tcx>,
    can_access_statics: bool,
) -> CompileTimeEvalContext<'mir, 'tcx> {
    debug!("mk_eval_cx: {:?}", param_env);
    InterpCx::new(
        tcx.at(span),
        param_env,
        CompileTimeInterpreter::new(),
        MemoryExtra { can_access_statics },
    )
}

fn op_to_const<'tcx>(
    ecx: &CompileTimeEvalContext<'_, 'tcx>,
    op: OpTy<'tcx>,
) -> &'tcx ty::Const<'tcx> {
    // We do not have value optimizations for everything.
    // Only scalars and slices, since they are very common.
    // Note that further down we turn scalars of undefined bits back to `ByRef`. These can result
    // from scalar unions that are initialized with one of their zero sized variants. We could
    // instead allow `ConstValue::Scalar` to store `ScalarMaybeUndef`, but that would affect all
    // the usual cases of extracting e.g. a `usize`, without there being a real use case for the
    // `Undef` situation.
    let try_as_immediate = match op.layout.abi {
        layout::Abi::Scalar(..) => true,
        layout::Abi::ScalarPair(..) => match op.layout.ty.kind {
            ty::Ref(_, inner, _) => match inner.kind {
                ty::Slice(elem) => elem == ecx.tcx.types.u8,
                ty::Str => true,
                _ => false,
            },
            _ => false,
        },
        _ => false,
    };
    let immediate = if try_as_immediate {
        Err(ecx.read_immediate(op).expect("normalization works on validated constants"))
    } else {
        // It is guaranteed that any non-slice scalar pair is actually ByRef here.
        // When we come back from raw const eval, we are always by-ref. The only way our op here is
        // by-val is if we are in const_field, i.e., if this is (a field of) something that we
        // "tried to make immediate" before. We wouldn't do that for non-slice scalar pairs or
        // structs containing such.
        op.try_as_mplace()
    };
    let val = match immediate {
        Ok(mplace) => {
            let ptr = mplace.ptr.to_ptr().unwrap();
            let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
            ConstValue::ByRef { alloc, offset: ptr.offset }
        }
        // see comment on `let try_as_immediate` above
        Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x {
            ScalarMaybeUndef::Scalar(s) => ConstValue::Scalar(s),
            ScalarMaybeUndef::Undef => {
                // When coming out of "normal CTFE", we'll always have an `Indirect` operand as
                // argument and we will not need this. The only way we can already have an
                // `Immediate` is when we are called from `const_field`, and that `Immediate`
                // comes from a constant so it can happen have `Undef`, because the indirect
                // memory that was read had undefined bytes.
                let mplace = op.assert_mem_place();
                let ptr = mplace.ptr.to_ptr().unwrap();
                let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
                ConstValue::ByRef { alloc, offset: ptr.offset }
            }
        },
        Err(ImmTy { imm: Immediate::ScalarPair(a, b), .. }) => {
            let (data, start) = match a.not_undef().unwrap() {
                Scalar::Ptr(ptr) => {
                    (ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id), ptr.offset.bytes())
                }
                Scalar::Raw { .. } => (
                    ecx.tcx.intern_const_alloc(Allocation::from_byte_aligned_bytes(b"" as &[u8])),
                    0,
                ),
            };
            let len = b.to_machine_usize(&ecx.tcx.tcx).unwrap();
            let start = start.try_into().unwrap();
            let len: usize = len.try_into().unwrap();
            ConstValue::Slice { data, start, end: start + len }
        }
    };
    ecx.tcx.mk_const(ty::Const { val: ty::ConstKind::Value(val), ty: op.layout.ty })
}

/// Extracts a field of a (variant of a) const.
// this function uses `unwrap` copiously, because an already validated constant must have valid
// fields and can thus never fail outside of compiler bugs
pub(crate) fn const_field<'tcx>(
    tcx: TyCtxt<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    variant: Option<VariantIdx>,
    field: mir::Field,
    value: &'tcx ty::Const<'tcx>,
) -> &'tcx ty::Const<'tcx> {
    trace!("const_field: {:?}, {:?}", field, value);
    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
    // get the operand again
    let op = ecx.eval_const_to_op(value, None).unwrap();
    // downcast
    let down = match variant {
        None => op,
        Some(variant) => ecx.operand_downcast(op, variant).unwrap(),
    };
    // then project
    let field = ecx.operand_field(down, field.index() as u64).unwrap();
    // and finally move back to the const world, always normalizing because
    // this is not called for statics.
    op_to_const(&ecx, field)
}

pub(crate) fn const_caller_location<'tcx>(
    tcx: TyCtxt<'tcx>,
    (file, line, col): (Symbol, u32, u32),
) -> &'tcx ty::Const<'tcx> {
    trace!("const_caller_location: {}:{}:{}", file, line, col);
    let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false);

    let loc_ty = tcx.caller_location_ty();
    let loc_place = ecx.alloc_caller_location(file, line, col);
    intern_const_alloc_recursive(&mut ecx, None, loc_place).unwrap();
    let loc_const = ty::Const {
        ty: loc_ty,
        val: ty::ConstKind::Value(ConstValue::Scalar(loc_place.ptr.into())),
    };

    tcx.mk_const(loc_const)
}

// this function uses `unwrap` copiously, because an already validated constant must have valid
// fields and can thus never fail outside of compiler bugs
pub(crate) fn const_variant_index<'tcx>(
    tcx: TyCtxt<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    val: &'tcx ty::Const<'tcx>,
) -> VariantIdx {
    trace!("const_variant_index: {:?}", val);
    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
    let op = ecx.eval_const_to_op(val, None).unwrap();
    ecx.read_discriminant(op).unwrap().1
}
<|endoftext|>


<commit_before>// Copyright 2012-2013 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.

//! Support for inlining external documentation into the current AST.

use syntax::ast;
use syntax::ast_util;
use syntax::attr::AttrMetaMethods;

use rustc::metadata::csearch;
use rustc::metadata::decoder;
use rustc::middle::ty;

use core;
use doctree;
use clean;

use super::Clean;

/// Attempt to inline the definition of a local node id into this AST.
///
/// This function will fetch the definition of the id specified, and if it is
/// from another crate it will attempt to inline the documentation from the
/// other crate into this crate.
///
/// This is primarily used for `pub use` statements which are, in general,
/// implementation details. Inlining the documentation should help provide a
/// better experience when reading the documentation in this use case.
///
/// The returned value is `None` if the `id` could not be inlined, and `Some`
/// of a vector of items if it was successfully expanded.
pub fn try_inline(id: ast::NodeId) -> Option<Vec<clean::Item>> {
    let cx = ::ctxtkey.get().unwrap();
    let tcx = match cx.maybe_typed {
        core::Typed(ref tycx) => tycx,
        core::NotTyped(_) => return None,
    };
    let def = match tcx.def_map.borrow().find(&id) {
        Some(def) => *def,
        None => return None,
    };
    let did = ast_util::def_id_of_def(def);
    if ast_util::is_local(did) { return None }
    try_inline_def(&**cx, tcx, def)
}

fn try_inline_def(cx: &core::DocContext,
                  tcx: &ty::ctxt,
                  def: ast::Def) -> Option<Vec<clean::Item>> {
    let mut ret = Vec::new();
    let did = ast_util::def_id_of_def(def);
    let inner = match def {
        ast::DefTrait(did) => {
            record_extern_fqn(cx, did, clean::TypeTrait);
            clean::TraitItem(build_external_trait(tcx, did))
        }
        ast::DefFn(did, style) => {
            record_extern_fqn(cx, did, clean::TypeFunction);
            clean::FunctionItem(build_external_function(tcx, did, style))
        }
        ast::DefStruct(did) => {
            record_extern_fqn(cx, did, clean::TypeStruct);
            ret.extend(build_impls(tcx, did).move_iter());
            clean::StructItem(build_struct(tcx, did))
        }
        ast::DefTy(did) => {
            record_extern_fqn(cx, did, clean::TypeEnum);
            ret.extend(build_impls(tcx, did).move_iter());
            build_type(tcx, did)
        }
        // Assume that the enum type is reexported next to the variant, and
        // variants don't show up in documentation specially.
        ast::DefVariant(..) => return Some(Vec::new()),
        ast::DefMod(did) => {
            record_extern_fqn(cx, did, clean::TypeModule);
            clean::ModuleItem(build_module(cx, tcx, did))
        }
        _ => return None,
    };
    let fqn = csearch::get_item_path(tcx, did);
    cx.inlined.borrow_mut().get_mut_ref().insert(did);
    ret.push(clean::Item {
        source: clean::Span::empty(),
        name: Some(fqn.last().unwrap().to_str().to_string()),
        attrs: load_attrs(tcx, did),
        inner: inner,
        visibility: Some(ast::Public),
        def_id: did,
    });
    Some(ret)
}

pub fn load_attrs(tcx: &ty::ctxt, did: ast::DefId) -> Vec<clean::Attribute> {
    let mut attrs = Vec::new();
    csearch::get_item_attrs(&tcx.sess.cstore, did, |v| {
        attrs.extend(v.move_iter().map(|mut a| {
            // FIXME this isn't quite always true, it's just true about 99% of
            //       the time when dealing with documentation. For example,
            //       this would treat doc comments of the form `#[doc = "foo"]`
            //       incorrectly.
            if a.name().get() == "doc" && a.value_str().is_some() {
                a.node.is_sugared_doc = true;
            }
            a.clean()
        }));
    });
    attrs
}

/// Record an external fully qualified name in the external_paths cache.
///
/// These names are used later on by HTML rendering to generate things like
/// source links back to the original item.
pub fn record_extern_fqn(cx: &core::DocContext,
                         did: ast::DefId,
                         kind: clean::TypeKind) {
    match cx.maybe_typed {
        core::Typed(ref tcx) => {
            let fqn = csearch::get_item_path(tcx, did);
            let fqn = fqn.move_iter().map(|i| i.to_str().to_string()).collect();
            cx.external_paths.borrow_mut().get_mut_ref().insert(did, (fqn, kind));
        }
        core::NotTyped(..) => {}
    }
}

pub fn build_external_trait(tcx: &ty::ctxt, did: ast::DefId) -> clean::Trait {
    let def = ty::lookup_trait_def(tcx, did);
    let methods = ty::trait_methods(tcx, did);
    clean::Trait {
        generics: def.generics.clean(),
        methods: methods.iter().map(|i| i.clean()).collect(),
        parents: Vec::new(), // FIXME: this is likely wrong
    }
}

fn build_external_function(tcx: &ty::ctxt,
                           did: ast::DefId,
                           style: ast::FnStyle) -> clean::Function {
    let t = ty::lookup_item_type(tcx, did);
    clean::Function {
        decl: match ty::get(t.ty).sty {
            ty::ty_bare_fn(ref f) => (did, &f.sig).clean(),
            _ => fail!("bad function"),
        },
        generics: t.generics.clean(),
        fn_style: style,
    }
}

fn build_struct(tcx: &ty::ctxt, did: ast::DefId) -> clean::Struct {
    use syntax::parse::token::special_idents::unnamed_field;

    let t = ty::lookup_item_type(tcx, did);
    let fields = ty::lookup_struct_fields(tcx, did);

    clean::Struct {
        struct_type: match fields.as_slice() {
            [] => doctree::Unit,
            [ref f] if f.name == unnamed_field.name => doctree::Newtype,
            [ref f, ..] if f.name == unnamed_field.name => doctree::Tuple,
            _ => doctree::Plain,
        },
        generics: t.generics.clean(),
        fields: fields.iter().map(|f| f.clean()).collect(),
        fields_stripped: false,
    }
}

fn build_type(tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEnum {
    let t = ty::lookup_item_type(tcx, did);
    match ty::get(t.ty).sty {
        ty::ty_enum(edid, _) => {
            return clean::EnumItem(clean::Enum {
                generics: t.generics.clean(),
                variants_stripped: false,
                variants: ty::enum_variants(tcx, edid).clean(),
            })
        }
        _ => {}
    }

    clean::TypedefItem(clean::Typedef {
        type_: t.ty.clean(),
        generics: t.generics.clean(),
    })
}

fn build_impls(tcx: &ty::ctxt,
               did: ast::DefId) -> Vec<clean::Item> {
    ty::populate_implementations_for_type_if_necessary(tcx, did);
    let mut impls = Vec::new();

    match tcx.inherent_impls.borrow().find(&did) {
        None => {}
        Some(i) => {
            impls.extend(i.borrow().iter().map(|&did| { build_impl(tcx, did) }));
        }
    }

    impls
}

fn build_impl(tcx: &ty::ctxt, did: ast::DefId) -> clean::Item {
    let associated_trait = csearch::get_impl_trait(tcx, did);
    let attrs = load_attrs(tcx, did);
    let ty = ty::lookup_item_type(tcx, did);
    let methods = csearch::get_impl_methods(&tcx.sess.cstore, did).iter().map(|did| {
        let mut item = match ty::method(tcx, *did).clean() {
            clean::Provided(item) => item,
            clean::Required(item) => item,
        };
        item.inner = match item.inner.clone() {
            clean::TyMethodItem(clean::TyMethod {
                fn_style, decl, self_, generics
            }) => {
                clean::MethodItem(clean::Method {
                    fn_style: fn_style,
                    decl: decl,
                    self_: self_,
                    generics: generics,
                })
            }
            _ => fail!("not a tymethod"),
        };
        item
    }).collect();
    clean::Item {
        inner: clean::ImplItem(clean::Impl {
            derived: clean::detect_derived(attrs.as_slice()),
            trait_: associated_trait.clean().map(|bound| {
                match bound {
                    clean::TraitBound(ty) => ty,
                    clean::RegionBound => unreachable!(),
                }
            }),
            for_: ty.ty.clean(),
            generics: ty.generics.clean(),
            methods: methods,
        }),
        source: clean::Span::empty(),
        name: None,
        attrs: attrs,
        visibility: Some(ast::Inherited),
        def_id: did,
    }
}

fn build_module(cx: &core::DocContext, tcx: &ty::ctxt,
                did: ast::DefId) -> clean::Module {
    let mut items = Vec::new();

    // FIXME: this doesn't handle reexports inside the module itself.
    //        Should they be handled?
    csearch::each_child_of_item(&tcx.sess.cstore, did, |def, _, _| {
        match def {
            decoder::DlDef(def) => {
                match try_inline_def(cx, tcx, def) {
                    Some(i) => items.extend(i.move_iter()),
                    None => {}
                }
            }
            decoder::DlImpl(did) => items.push(build_impl(tcx, did)),
            decoder::DlField => fail!("unimplemented field"),
        }
    });

    clean::Module {
        items: items,
        is_crate: false,
    }
}
<commit_msg>rustdoc: Filter inlining private external items<commit_after>// Copyright 2012-2013 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.

//! Support for inlining external documentation into the current AST.

use syntax::ast;
use syntax::ast_util;
use syntax::attr::AttrMetaMethods;

use rustc::metadata::csearch;
use rustc::metadata::decoder;
use rustc::middle::ty;

use core;
use doctree;
use clean;

use super::Clean;

/// Attempt to inline the definition of a local node id into this AST.
///
/// This function will fetch the definition of the id specified, and if it is
/// from another crate it will attempt to inline the documentation from the
/// other crate into this crate.
///
/// This is primarily used for `pub use` statements which are, in general,
/// implementation details. Inlining the documentation should help provide a
/// better experience when reading the documentation in this use case.
///
/// The returned value is `None` if the `id` could not be inlined, and `Some`
/// of a vector of items if it was successfully expanded.
pub fn try_inline(id: ast::NodeId) -> Option<Vec<clean::Item>> {
    let cx = ::ctxtkey.get().unwrap();
    let tcx = match cx.maybe_typed {
        core::Typed(ref tycx) => tycx,
        core::NotTyped(_) => return None,
    };
    let def = match tcx.def_map.borrow().find(&id) {
        Some(def) => *def,
        None => return None,
    };
    let did = ast_util::def_id_of_def(def);
    if ast_util::is_local(did) { return None }
    try_inline_def(&**cx, tcx, def)
}

fn try_inline_def(cx: &core::DocContext,
                  tcx: &ty::ctxt,
                  def: ast::Def) -> Option<Vec<clean::Item>> {
    let mut ret = Vec::new();
    let did = ast_util::def_id_of_def(def);
    let inner = match def {
        ast::DefTrait(did) => {
            record_extern_fqn(cx, did, clean::TypeTrait);
            clean::TraitItem(build_external_trait(tcx, did))
        }
        ast::DefFn(did, style) => {
            record_extern_fqn(cx, did, clean::TypeFunction);
            clean::FunctionItem(build_external_function(tcx, did, style))
        }
        ast::DefStruct(did) => {
            record_extern_fqn(cx, did, clean::TypeStruct);
            ret.extend(build_impls(tcx, did).move_iter());
            clean::StructItem(build_struct(tcx, did))
        }
        ast::DefTy(did) => {
            record_extern_fqn(cx, did, clean::TypeEnum);
            ret.extend(build_impls(tcx, did).move_iter());
            build_type(tcx, did)
        }
        // Assume that the enum type is reexported next to the variant, and
        // variants don't show up in documentation specially.
        ast::DefVariant(..) => return Some(Vec::new()),
        ast::DefMod(did) => {
            record_extern_fqn(cx, did, clean::TypeModule);
            clean::ModuleItem(build_module(cx, tcx, did))
        }
        _ => return None,
    };
    let fqn = csearch::get_item_path(tcx, did);
    cx.inlined.borrow_mut().get_mut_ref().insert(did);
    ret.push(clean::Item {
        source: clean::Span::empty(),
        name: Some(fqn.last().unwrap().to_str().to_string()),
        attrs: load_attrs(tcx, did),
        inner: inner,
        visibility: Some(ast::Public),
        def_id: did,
    });
    Some(ret)
}

pub fn load_attrs(tcx: &ty::ctxt, did: ast::DefId) -> Vec<clean::Attribute> {
    let mut attrs = Vec::new();
    csearch::get_item_attrs(&tcx.sess.cstore, did, |v| {
        attrs.extend(v.move_iter().map(|mut a| {
            // FIXME this isn't quite always true, it's just true about 99% of
            //       the time when dealing with documentation. For example,
            //       this would treat doc comments of the form `#[doc = "foo"]`
            //       incorrectly.
            if a.name().get() == "doc" && a.value_str().is_some() {
                a.node.is_sugared_doc = true;
            }
            a.clean()
        }));
    });
    attrs
}

/// Record an external fully qualified name in the external_paths cache.
///
/// These names are used later on by HTML rendering to generate things like
/// source links back to the original item.
pub fn record_extern_fqn(cx: &core::DocContext,
                         did: ast::DefId,
                         kind: clean::TypeKind) {
    match cx.maybe_typed {
        core::Typed(ref tcx) => {
            let fqn = csearch::get_item_path(tcx, did);
            let fqn = fqn.move_iter().map(|i| i.to_str().to_string()).collect();
            cx.external_paths.borrow_mut().get_mut_ref().insert(did, (fqn, kind));
        }
        core::NotTyped(..) => {}
    }
}

pub fn build_external_trait(tcx: &ty::ctxt, did: ast::DefId) -> clean::Trait {
    let def = ty::lookup_trait_def(tcx, did);
    let methods = ty::trait_methods(tcx, did);
    clean::Trait {
        generics: def.generics.clean(),
        methods: methods.iter().map(|i| i.clean()).collect(),
        parents: Vec::new(), // FIXME: this is likely wrong
    }
}

fn build_external_function(tcx: &ty::ctxt,
                           did: ast::DefId,
                           style: ast::FnStyle) -> clean::Function {
    let t = ty::lookup_item_type(tcx, did);
    clean::Function {
        decl: match ty::get(t.ty).sty {
            ty::ty_bare_fn(ref f) => (did, &f.sig).clean(),
            _ => fail!("bad function"),
        },
        generics: t.generics.clean(),
        fn_style: style,
    }
}

fn build_struct(tcx: &ty::ctxt, did: ast::DefId) -> clean::Struct {
    use syntax::parse::token::special_idents::unnamed_field;

    let t = ty::lookup_item_type(tcx, did);
    let fields = ty::lookup_struct_fields(tcx, did);

    clean::Struct {
        struct_type: match fields.as_slice() {
            [] => doctree::Unit,
            [ref f] if f.name == unnamed_field.name => doctree::Newtype,
            [ref f, ..] if f.name == unnamed_field.name => doctree::Tuple,
            _ => doctree::Plain,
        },
        generics: t.generics.clean(),
        fields: fields.iter().map(|f| f.clean()).collect(),
        fields_stripped: false,
    }
}

fn build_type(tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEnum {
    let t = ty::lookup_item_type(tcx, did);
    match ty::get(t.ty).sty {
        ty::ty_enum(edid, _) => {
            return clean::EnumItem(clean::Enum {
                generics: t.generics.clean(),
                variants_stripped: false,
                variants: ty::enum_variants(tcx, edid).clean(),
            })
        }
        _ => {}
    }

    clean::TypedefItem(clean::Typedef {
        type_: t.ty.clean(),
        generics: t.generics.clean(),
    })
}

fn build_impls(tcx: &ty::ctxt,
               did: ast::DefId) -> Vec<clean::Item> {
    ty::populate_implementations_for_type_if_necessary(tcx, did);
    let mut impls = Vec::new();

    match tcx.inherent_impls.borrow().find(&did) {
        None => {}
        Some(i) => {
            impls.extend(i.borrow().iter().map(|&did| { build_impl(tcx, did) }));
        }
    }

    impls
}

fn build_impl(tcx: &ty::ctxt, did: ast::DefId) -> clean::Item {
    let associated_trait = csearch::get_impl_trait(tcx, did);
    let attrs = load_attrs(tcx, did);
    let ty = ty::lookup_item_type(tcx, did);
    let methods = csearch::get_impl_methods(&tcx.sess.cstore, did).iter().map(|did| {
        let mut item = match ty::method(tcx, *did).clean() {
            clean::Provided(item) => item,
            clean::Required(item) => item,
        };
        item.inner = match item.inner.clone() {
            clean::TyMethodItem(clean::TyMethod {
                fn_style, decl, self_, generics
            }) => {
                clean::MethodItem(clean::Method {
                    fn_style: fn_style,
                    decl: decl,
                    self_: self_,
                    generics: generics,
                })
            }
            _ => fail!("not a tymethod"),
        };
        item
    }).collect();
    clean::Item {
        inner: clean::ImplItem(clean::Impl {
            derived: clean::detect_derived(attrs.as_slice()),
            trait_: associated_trait.clean().map(|bound| {
                match bound {
                    clean::TraitBound(ty) => ty,
                    clean::RegionBound => unreachable!(),
                }
            }),
            for_: ty.ty.clean(),
            generics: ty.generics.clean(),
            methods: methods,
        }),
        source: clean::Span::empty(),
        name: None,
        attrs: attrs,
        visibility: Some(ast::Inherited),
        def_id: did,
    }
}

fn build_module(cx: &core::DocContext, tcx: &ty::ctxt,
                did: ast::DefId) -> clean::Module {
    let mut items = Vec::new();

    // FIXME: this doesn't handle reexports inside the module itself.
    //        Should they be handled?
    csearch::each_child_of_item(&tcx.sess.cstore, did, |def, _, vis| {
        if vis != ast::Public { return }
        match def {
            decoder::DlDef(def) => {
                match try_inline_def(cx, tcx, def) {
                    Some(i) => items.extend(i.move_iter()),
                    None => {}
                }
            }
            decoder::DlImpl(did) => items.push(build_impl(tcx, did)),
            decoder::DlField => fail!("unimplemented field"),
        }
    });

    clean::Module {
        items: items,
        is_crate: false,
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

//! Implementation of cross-process surfaces for Linux. This uses X pixmaps.

use platform::surface::NativeSurfaceMethods;
use texturegl::Texture;

use geom::size::Size2D;
use opengles::glx::{GLXFBConfig, GLXDrawable, GLX_BIND_TO_TEXTURE_RGBA_EXT};
use opengles::glx::{GLX_DEPTH_SIZE, GLX_DRAWABLE_TYPE, GLX_FRONT_EXT, GLX_PIXMAP_BIT, GLX_RGBA};
use opengles::glx::{GLX_TEXTURE_2D_EXT, GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT};
use opengles::glx::{GLX_TEXTURE_TARGET_EXT, glXChooseVisual, glXCreatePixmap, glXDestroyPixmap};
use opengles::glx::{glXGetProcAddress, glXGetFBConfigAttrib, glXGetFBConfigs};
use opengles::glx::{glXGetVisualFromFBConfig};
use opengles::glx;
use opengles::gl2::NO_ERROR;
use opengles::gl2;
use std::cast;
use std::libc::{c_int, c_uint, c_void};
use std::ptr;
use xlib::xlib::{Display, Pixmap, XCloseDisplay, XCreateGC, XCreateImage, XCreatePixmap};
use xlib::xlib::{XDefaultScreen, XFreePixmap, XGetGeometry, XOpenDisplay, XPutImage, XRootWindow};
use xlib::xlib::{XVisualInfo, ZPixmap};

/// The display and visual info. This is needed in order to upload on the painting side. This holds
/// a *strong* reference to the display and will close it when done.
///
/// FIXME(pcwalton): Mark nonsendable and noncopyable.
pub struct NativePaintingGraphicsContext {
    display: *Display,
    visual_info: *XVisualInfo,
}

impl NativePaintingGraphicsContext {
    pub fn from_metadata(metadata: &NativeGraphicsMetadata) -> NativePaintingGraphicsContext {
        unsafe {
            let display = metadata.display.with_c_str(|c_str| {
                XOpenDisplay(c_str)
            });

            if display.is_null() {
                fail!("XOpenDisplay() failed!");
            }

            // FIXME(pcwalton): It would be more robust to actually have the compositor pass the
            // visual.
            let compositor_visual_info =
                NativeCompositingGraphicsContext::compositor_visual_info(display);

            NativePaintingGraphicsContext {
                display: display,
                visual_info: compositor_visual_info,
            }
        }
    }
}

impl Drop for NativePaintingGraphicsContext {
    fn drop(&mut self) {
        unsafe {
            let _ = XCloseDisplay(self.display);
        }
    }
}

/// The display, visual info, and framebuffer configuration. This is needed in order to bind to a
/// texture on the compositor side. This holds only a *weak* reference to the display and does not
/// close it.
///
/// FIXME(pcwalton): Unchecked weak references are bad and can violate memory safety. This is hard
/// to fix because the Display is given to us by the native windowing system, but we should fix it
/// someday.
///
/// FIXME(pcwalton): Mark nonsendable.
pub struct NativeCompositingGraphicsContext {
    display: *Display,
    visual_info: *XVisualInfo,
    framebuffer_configuration: GLXFBConfig,
}

impl NativeCompositingGraphicsContext {
    /// Chooses the compositor visual info using the same algorithm that the compositor uses.
    ///
    /// FIXME(pcwalton): It would be more robust to actually have the compositor pass the visual.
    fn compositor_visual_info(display: *Display) -> *XVisualInfo {
        unsafe {
            let glx_display: *glx::Display = cast::transmute(display);
            let screen = XDefaultScreen(display);
            let attributes = [ GLX_RGBA, GLX_DEPTH_SIZE, 24, 0 ];
            let compositor_visual_info = glXChooseVisual(glx_display, screen, &attributes[0]);
            cast::transmute(compositor_visual_info)
        }
    }

    /// Creates a native graphics context from the given X display connection. This uses GLX. Only
    /// the compositor is allowed to call this.
    pub fn from_display(display: *Display) -> NativeCompositingGraphicsContext {
        unsafe {
            // FIXME(pcwalton): It would be more robust to actually have the compositor pass the
            // visual.
            let compositor_visual_info =
                NativeCompositingGraphicsContext::compositor_visual_info(display);
            let compositor_visual_id = (*compositor_visual_info).visualid;

            // Choose an FB config.
            let glx_display = cast::transmute(display);
            let screen = XDefaultScreen(display);
            let mut fbconfig_count = 0;
            let fbconfigs = glXGetFBConfigs(glx_display, screen, &mut fbconfig_count);
            let mut fbconfig_index = None;
            for i in range(0, fbconfig_count) {
                let fbconfig = *ptr::offset(fbconfigs, i as int);
                let visual_info = glXGetVisualFromFBConfig(glx_display, fbconfig);
                let visual_info: *XVisualInfo = cast::transmute(visual_info);
                if visual_info == ptr::null() || (*visual_info).visualid != compositor_visual_id {
                    continue
                }

                let mut value = 0;
                glXGetFBConfigAttrib(glx_display, fbconfig, GLX_DRAWABLE_TYPE, &mut value);
                if (value & GLX_PIXMAP_BIT) == 0 {
                    continue
                }

                glXGetFBConfigAttrib(glx_display,
                                     fbconfig,
                                     GLX_BIND_TO_TEXTURE_RGBA_EXT,
                                     &mut value);
                if value == 0 {
                    continue
                }

                fbconfig_index = Some(i);
                break
            }

            let framebuffer_configuration = match fbconfig_index {
                None => fail!("No appropriate framebuffer config found!"),
                Some(index) => *ptr::offset(fbconfigs, index as int),
            };

            NativeCompositingGraphicsContext {
                display: display,
                visual_info: compositor_visual_info,
                framebuffer_configuration: framebuffer_configuration,
            }
        }
    }
}

/// The X display string.
#[deriving(Clone)]
pub struct NativeGraphicsMetadata {
    display: ~str,
}

impl NativeGraphicsMetadata {
    /// Creates graphics metadata from a metadata descriptor.
    pub fn from_descriptor(descriptor: &NativeGraphicsMetadataDescriptor)
                           -> NativeGraphicsMetadata {
        NativeGraphicsMetadata {
            display: descriptor.display.to_str(),
        }
    }
}

/// A sendable form of the X display string.
#[deriving(Clone, Decodable, Encodable)]
pub struct NativeGraphicsMetadataDescriptor {
    display: ~str,
}

impl NativeGraphicsMetadataDescriptor {
    /// Creates a metadata descriptor from metadata.
    pub fn from_metadata(metadata: NativeGraphicsMetadata) -> NativeGraphicsMetadataDescriptor {
        NativeGraphicsMetadataDescriptor {
            display: metadata.display.to_str()
        }
    }
}

#[deriving(Eq)]
pub enum NativeSurfaceTransientData {
    NoTransientData,
    RenderTaskTransientData(*Display, *XVisualInfo),
}

#[deriving(Decodable, Encodable)]
pub struct NativeSurface {
    /// The pixmap.
    pixmap: Pixmap,

    /// Whether this pixmap will leak if the destructor runs. This is for debugging purposes.
    will_leak: bool,
}

impl Drop for NativeSurface {
    fn drop(&mut self) {
        if self.will_leak {
            fail!("You should have disposed of the pixmap properly with destroy()! This pixmap \
                   will leak!");
        }
    }
}

impl NativeSurface {
    pub fn from_pixmap(pixmap: Pixmap) -> NativeSurface {
        NativeSurface {
            pixmap: pixmap,
            will_leak: true,
        }
    }
}

impl NativeSurfaceMethods for NativeSurface {
    fn new(native_context: &NativePaintingGraphicsContext, size: Size2D<i32>, stride: i32)
           -> NativeSurface {
        unsafe {
            // Create the pixmap.
            let screen = XDefaultScreen(native_context.display);
            let window = XRootWindow(native_context.display, screen);

            let pixmap = XCreatePixmap(native_context.display,
                                       window,
                                       size.width as c_uint,
                                       size.height as c_uint,
                                       ((stride / size.width) * 8) as c_uint);

            NativeSurface::from_pixmap(pixmap)
        }
    }

    /// This may only be called on the compositor side.
    fn bind_to_texture(&self,
                       native_context: &NativeCompositingGraphicsContext,
                       texture: &Texture,
                       _size: Size2D<int>) {
        unsafe {
            // Create the GLX pixmap.
            //
            // FIXME(pcwalton): RAII for exception safety?
            let pixmap_attributes = [
                GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
                GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
                0
            ];
            let glx_display = cast::transmute(native_context.display);
            let glx_pixmap = glXCreatePixmap(glx_display,
                                             native_context.framebuffer_configuration,
                                             self.pixmap,
                                             &pixmap_attributes[0]);

            let glXBindTexImageEXT: extern "C" fn(*Display, GLXDrawable, c_int, *c_int) =
                cast::transmute(glXGetProcAddress(cast::transmute(&"glXBindTexImageEXT\x00"[0])));
            assert!(glXBindTexImageEXT as *c_void != ptr::null());
            let _bound = texture.bind();
            glXBindTexImageEXT(native_context.display,
                               cast::transmute(glx_pixmap),
                               GLX_FRONT_EXT,
                               ptr::null());
            assert_eq!(gl2::get_error(), NO_ERROR);

            // FIXME(pcwalton): Recycle these for speed?
            glXDestroyPixmap(glx_display, glx_pixmap);
        }
    }

    /// This may only be called on the painting side.
    fn upload(&self, graphics_context: &NativePaintingGraphicsContext, data: &[u8]) {
        unsafe {
            // Ensure that we're running on the render task. Take the display.
            let pixmap = self.pixmap;

            // Figure out the width, height, and depth of the pixmap.
            let mut root_window = 0;
            let mut x = 0;
            let mut y = 0;
            let mut width = 0;
            let mut height = 0;
            let mut border_width = 0;
            let mut depth = 0;
            let _ = XGetGeometry(graphics_context.display,
                                 cast::transmute(pixmap),
                                 &mut root_window,
                                 &mut x,
                                 &mut y,
                                 &mut width,
                                 &mut height,
                                 &mut border_width,
                                 &mut depth);

            // Create the image.
            let image = XCreateImage(graphics_context.display,
                                     (*graphics_context.visual_info).visual,
                                     depth,
                                     ZPixmap,
                                     0,
                                     cast::transmute(&data[0]),
                                     width as c_uint,
                                     height as c_uint,
                                     32,
                                     0);

            // Create the X graphics context.
            let gc = XCreateGC(graphics_context.display, pixmap, 0, ptr::null());

            // Draw the image.
            let _ = XPutImage(graphics_context.display,
                              pixmap,
                              gc,
                              image,
                              0,
                              0,
                              0,
                              0,
                              width,
                              height);
        }
    }

    fn get_id(&self) -> int {
        self.pixmap as int
    }

    fn destroy(&mut self, graphics_context: &NativePaintingGraphicsContext) {
        unsafe {
            assert!(self.pixmap != 0);
            XFreePixmap(graphics_context.display, self.pixmap);
            self.mark_wont_leak()
        }
    }

    fn mark_will_leak(&mut self) {
        self.will_leak = true
    }

    fn mark_wont_leak(&mut self) {
        self.will_leak = false
    }
}

<commit_msg>Add support for NVidia cards.<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

//! Implementation of cross-process surfaces for Linux. This uses X pixmaps.

use platform::surface::NativeSurfaceMethods;
use texturegl::Texture;

use geom::size::Size2D;
use opengles::glx::{GLXFBConfig, GLXDrawable};
use opengles::glx::{GLX_BIND_TO_TEXTURE_RGBA_EXT};
use opengles::glx::{GLX_DRAWABLE_TYPE, GLX_FRONT_EXT, GLX_PIXMAP_BIT};
use opengles::glx::{GLX_TEXTURE_2D_EXT, GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT};
use opengles::glx::{GLX_TEXTURE_TARGET_EXT, glXCreatePixmap, glXDestroyPixmap};
use opengles::glx::{glXGetProcAddress, glXChooseFBConfig};
use opengles::glx::{glXGetVisualFromFBConfig};
use opengles::glx::{GLX_RGBA_BIT, GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_DOUBLEBUFFER};
use opengles::gl2::NO_ERROR;
use opengles::gl2;
use std::cast;
use std::c_str::CString;
use std::libc::{c_int, c_uint, c_void};
use std::ptr;
use xlib::xlib::{Display, Pixmap, XCreateGC, XCreateImage, XCreatePixmap, XDefaultScreen};
use xlib::xlib::{XDisplayString, XFreePixmap, XGetGeometry, XOpenDisplay, XPutImage, XRootWindow};
use xlib::xlib::{XVisualInfo, ZPixmap};

/// The display and visual info. This is needed in order to upload on the painting side. This
/// holds a weak reference to the display and will not close it when done.
///
/// FIXME(pcwalton): Mark nonsendable and noncopyable.
pub struct NativePaintingGraphicsContext {
    display: *Display,
    visual_info: *XVisualInfo,
}

impl NativePaintingGraphicsContext {
    pub fn from_metadata(metadata: &NativeGraphicsMetadata) -> NativePaintingGraphicsContext {
        // FIXME(pcwalton): It would be more robust to actually have the compositor pass the
        // visual.
        let (compositor_visual_info, _) =
            NativeCompositingGraphicsContext::compositor_visual_info(metadata.display);

        NativePaintingGraphicsContext {
            display: metadata.display,
            visual_info: compositor_visual_info,
        }
    }
}

/// The display, visual info, and framebuffer configuration. This is needed in order to bind to a
/// texture on the compositor side. This holds only a *weak* reference to the display and does not
/// close it.
///
/// FIXME(pcwalton): Unchecked weak references are bad and can violate memory safety. This is hard
/// to fix because the Display is given to us by the native windowing system, but we should fix it
/// someday.
///
/// FIXME(pcwalton): Mark nonsendable.
pub struct NativeCompositingGraphicsContext {
    display: *Display,
    visual_info: *XVisualInfo,
    framebuffer_configuration: Option<GLXFBConfig>,
}

impl NativeCompositingGraphicsContext {
    /// Chooses the compositor visual info using the same algorithm that the compositor uses.
    ///
    /// FIXME(pcwalton): It would be more robust to actually have the compositor pass the visual.
    fn compositor_visual_info(display: *Display) -> (*XVisualInfo, Option<GLXFBConfig>) {
        unsafe {
            let glx_display = cast::transmute(display);

            // CONSIDER:
            // In skia, they compute the GLX_ALPHA_SIZE minimum and request
            // that as well.

            let fbconfig_attributes = [
                GLX_DOUBLEBUFFER, 0,
                GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT | GLX_WINDOW_BIT,
                GLX_BIND_TO_TEXTURE_RGBA_EXT, 1,
                GLX_RENDER_TYPE, GLX_RGBA_BIT,
                0
            ];

            let screen = XDefaultScreen(display);
            let mut configs = 0;
            let fbconfigs = glXChooseFBConfig(glx_display, screen,
                                              &fbconfig_attributes[0], &mut configs);
            if (configs == 0) {
                fail!("Unable to locate a GLX FB configuration that supports RGBA.");
            }

            let fbconfig = *ptr::offset(fbconfigs, 0);
            let vi = glXGetVisualFromFBConfig(glx_display, fbconfig);
            (cast::transmute(vi), Some(fbconfig))
        }
    }

    /// Creates a native graphics context from the given X display connection. This uses GLX. Only
    /// the compositor is allowed to call this.
    pub fn from_display(display: *Display) -> NativeCompositingGraphicsContext {
        let (visual_info, fbconfig) = NativeCompositingGraphicsContext::compositor_visual_info(display);

        NativeCompositingGraphicsContext {
            display: display,
            visual_info: visual_info,
            framebuffer_configuration: fbconfig,
        }
    }
}

/// The X display.
#[deriving(Clone)]
pub struct NativeGraphicsMetadata {
    display: *Display,
}

impl NativeGraphicsMetadata {
    /// Creates graphics metadata from a metadata descriptor.
    pub fn from_descriptor(descriptor: &NativeGraphicsMetadataDescriptor)
                           -> NativeGraphicsMetadata {
        // WARNING: We currently rely on the X display connection being the
        // same in both the Painting and Compositing contexts, as otherwise
        // the X Pixmap will not be sharable across them. Using this
        // method breaks that assumption.
        unsafe {
            let display = descriptor.display.with_c_str(|c_str| {
                    XOpenDisplay(c_str)
                });

            if display.is_null() {
                fail!("XOpenDisplay() failed!");
            }

            NativeGraphicsMetadata {
                display: display,
            }
        }
    }
}

/// A sendable form of the X display string.
#[deriving(Clone, Decodable, Encodable)]
pub struct NativeGraphicsMetadataDescriptor {
    display: ~str,
}

impl NativeGraphicsMetadataDescriptor {
    /// Creates a metadata descriptor from metadata.
    pub fn from_metadata(metadata: NativeGraphicsMetadata) -> NativeGraphicsMetadataDescriptor {
        unsafe {
            let c_str = CString::new(XDisplayString(metadata.display), false);
            NativeGraphicsMetadataDescriptor {
                display: c_str.as_str().unwrap().to_str(),
            }
        }
    }
}

#[deriving(Eq)]
pub enum NativeSurfaceTransientData {
    NoTransientData,
    RenderTaskTransientData(*Display, *XVisualInfo),
}

#[deriving(Decodable, Encodable)]
pub struct NativeSurface {
    /// The pixmap.
    pixmap: Pixmap,

    /// Whether this pixmap will leak if the destructor runs. This is for debugging purposes.
    will_leak: bool,
}

impl Drop for NativeSurface {
    fn drop(&mut self) {
        if self.will_leak {
            fail!("You should have disposed of the pixmap properly with destroy()! This pixmap \
                   will leak!");
        }
    }
}

impl NativeSurface {
    pub fn from_pixmap(pixmap: Pixmap) -> NativeSurface {
        NativeSurface {
            pixmap: pixmap,
            will_leak: true,
        }
    }
}

impl NativeSurfaceMethods for NativeSurface {
    fn new(native_context: &NativePaintingGraphicsContext, size: Size2D<i32>, stride: i32)
           -> NativeSurface {
        unsafe {
            // Create the pixmap.
            let screen = XDefaultScreen(native_context.display);
            let window = XRootWindow(native_context.display, screen);
            let pixmap = XCreatePixmap(native_context.display,
                                       window,
                                       size.width as c_uint,
                                       size.height as c_uint,
                                       ((stride / size.width) * 8) as c_uint);
            NativeSurface::from_pixmap(pixmap)
        }
    }

    /// This may only be called on the compositor side.
    fn bind_to_texture(&self,
                       native_context: &NativeCompositingGraphicsContext,
                       texture: &Texture,
                       _size: Size2D<int>) {
        unsafe {
            // Create the GLX pixmap.
            //
            // FIXME(pcwalton): RAII for exception safety?
            let pixmap_attributes = [
                GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
                GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
                0
            ];

            let glx_display = cast::transmute(native_context.display);

            let glx_pixmap = glXCreatePixmap(glx_display,
                                             native_context.framebuffer_configuration.expect(
                                                 "GLX 1.3 should have a framebuffer_configuration"),
                                             self.pixmap,
                                             &pixmap_attributes[0]);

            let glXBindTexImageEXT: extern "C" fn(*Display, GLXDrawable, c_int, *c_int) =
                cast::transmute(glXGetProcAddress(cast::transmute(&"glXBindTexImageEXT\x00"[0])));
            assert!(glXBindTexImageEXT as *c_void != ptr::null());
            let _bound = texture.bind();
            glXBindTexImageEXT(native_context.display,
                               cast::transmute(glx_pixmap),
                               GLX_FRONT_EXT,
                               ptr::null());
            assert_eq!(gl2::get_error(), NO_ERROR);

            // FIXME(pcwalton): Recycle these for speed?
            glXDestroyPixmap(glx_display, glx_pixmap);
        }
    }

    /// This may only be called on the painting side.
    fn upload(&self, graphics_context: &NativePaintingGraphicsContext, data: &[u8]) {
        unsafe {
            // Ensure that we're running on the render task. Take the display.
            let pixmap = self.pixmap;

            // Figure out the width, height, and depth of the pixmap.
            let mut root_window = 0;
            let mut x = 0;
            let mut y = 0;
            let mut width = 0;
            let mut height = 0;
            let mut border_width = 0;
            let mut depth = 0;
            let _ = XGetGeometry(graphics_context.display,
                                 cast::transmute(pixmap),
                                 &mut root_window,
                                 &mut x,
                                 &mut y,
                                 &mut width,
                                 &mut height,
                                 &mut border_width,
                                 &mut depth);

            // Create the image.
            let image = XCreateImage(graphics_context.display,
                                     (*graphics_context.visual_info).visual,
                                     depth,
                                     ZPixmap,
                                     0,
                                     cast::transmute(&data[0]),
                                     width as c_uint,
                                     height as c_uint,
                                     32,
                                     0);

            // Create the X graphics context.
            let gc = XCreateGC(graphics_context.display, pixmap, 0, ptr::null());

            // Draw the image.
            let _ = XPutImage(graphics_context.display,
                              pixmap,
                              gc,
                              image,
                              0,
                              0,
                              0,
                              0,
                              width,
                              height);
        }
    }

    fn get_id(&self) -> int {
        self.pixmap as int
    }

    fn destroy(&mut self, graphics_context: &NativePaintingGraphicsContext) {
        unsafe {
            assert!(self.pixmap != 0);
            XFreePixmap(graphics_context.display, self.pixmap);
            self.mark_wont_leak()
        }
    }

    fn mark_will_leak(&mut self) {
        self.will_leak = true
    }

    fn mark_wont_leak(&mut self) {
        self.will_leak = false
    }
}

<|endoftext|>


<commit_before>// Copyright © 2015, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
//! FFI bindings to secur32.
#![cfg(windows)]
extern crate winapi;
use winapi::*;
extern "system" {
    pub fn AcceptSecurityContext(
        phCredential: PCredHandle, phContext: PCtxtHandle, pInput: PSecBufferDesc,
        fContextReq: c_ulong, TargetDataRep: c_ulong, phNewContext: PCtxtHandle,
        pOutput: PSecBufferDesc, pfContextAttr: *mut c_ulong, ptsExpiry: PTimeStamp,
    ) -> SECURITY_STATUS;
    pub fn AcquireCredentialsHandleA(
        pszPrincipal: LPSTR, pszPackage: LPSTR, fCredentialUse: c_ulong, pvLogonId: *mut c_void,
        pAuthData: *mut c_void, pGetKeyFn: SEC_GET_KEY_FN, pvGetKeyArgument: *mut c_void,
        phCredential: PCredHandle, ptsExpiry: PTimeStamp,
    ) -> SECURITY_STATUS;
    pub fn AcquireCredentialsHandleW(
        pszPrincipal: LPWSTR, pszPackage: LPWSTR, fCredentialUse: c_ulong, pvLogonId: *mut c_void,
        pAuthData: *mut c_void, pGetKeyFn: SEC_GET_KEY_FN, pvGetKeyArgument: *mut c_void,
        phCredential: PCredHandle, ptsExpiry: PTimeStamp,
    ) -> SECURITY_STATUS;
    pub fn AddCredentialsA(
        hCredentials: PCredHandle, pszPrincipal: LPSTR, pszPackage: LPSTR, fCredentialUse: c_ulong,
        pAuthData: *mut c_void, pGetKeyFn: SEC_GET_KEY_FN, pvGetKeyArgument: *mut c_void,
        ptsExpiry: PTimeStamp,
    ) -> SECURITY_STATUS;
    pub fn AddCredentialsW(
        hCredentials: PCredHandle, pszPrincipal: LPWSTR, pszPackage: LPWSTR,
        fCredentialUse: c_ulong, pAuthData: *mut c_void, pGetKeyFn: SEC_GET_KEY_FN,
        pvGetKeyArgument: *mut c_void, ptsExpiry: PTimeStamp,
    ) -> SECURITY_STATUS;
    // pub fn AddSecurityPackageA();
    // pub fn AddSecurityPackageW();
    pub fn ApplyControlToken(phContext: PCtxtHandle, pInput: PSecBufferDesc) -> SECURITY_STATUS;
    pub fn ChangeAccountPasswordA(
        pszPackageName: *mut SEC_CHAR, pszDomainName: *mut SEC_CHAR, pszAccountName: *mut SEC_CHAR, pszOldPassword: *mut SEC_CHAR, pszNewPassword: *mut SEC_CHAR, bImpersonating: BOOLEAN,
        dwReserved: c_ulong, pOutput: PSecBufferDesc,
    ) -> SECURITY_STATUS;
    pub fn ChangeAccountPasswordW(
        pszPackageName: *mut SEC_WCHAR, pszDomainName: *mut SEC_WCHAR,
        pszAccountName: *mut SEC_WCHAR, pszOldPassword: *mut SEC_WCHAR,
        pszNewPassword: *mut SEC_WCHAR, bImpersonating: BOOLEAN, dwReserved: c_ulong,
        pOutput: PSecBufferDesc,
    ) -> SECURITY_STATUS;
    pub fn CompleteAuthToken(phContext: PCtxtHandle, pToken: PSecBufferDesc) -> SECURITY_STATUS;
    pub fn DecryptMessage(
        phContext: PCtxtHandle, pMessage: PSecBufferDesc, MessageSeqNo: c_ulong,
        pfQOP: *mut c_ulong,
    ) -> SECURITY_STATUS;
    pub fn DeleteSecurityContext(phContext: PCtxtHandle) -> SECURITY_STATUS;
    // pub fn DeleteSecurityPackageA();
    // pub fn DeleteSecurityPackageW();
    pub fn EncryptMessage(
        phContext: PCtxtHandle, fQOP: c_ulong, pMessage: PSecBufferDesc, MessageSeqNo: c_ulong,
    ) -> SECURITY_STATUS;
    pub fn EnumerateSecurityPackagesA(
        pcPackages: *mut c_ulong, ppPackageInfo: *mut PSecPkgInfoA,
    ) -> SECURITY_STATUS;
    pub fn EnumerateSecurityPackagesW(
        pcPackages: *mut c_ulong, ppPackageInfo: *mut PSecPkgInfoW,
    ) -> SECURITY_STATUS;
    pub fn ExportSecurityContext(
        phContext: PCtxtHandle, fFlags: ULONG, pPackedContext: PSecBuffer,
        pToken: *mut *mut c_void,
    ) -> SECURITY_STATUS;
    pub fn FreeContextBuffer(pvContextBuffer: PVOID) -> SECURITY_STATUS;
    pub fn FreeCredentialsHandle(phCredential: PCredHandle) -> SECURITY_STATUS;
    // pub fn GetComputerObjectNameA();
    // pub fn GetComputerObjectNameW();
    // pub fn GetSecurityUserInfo();
    // pub fn GetUserNameExA();
    // pub fn GetUserNameExW();
    pub fn ImpersonateSecurityContext(phContext: PCtxtHandle) -> SECURITY_STATUS;
    pub fn ImportSecurityContextA(
        pszPackage: LPSTR, pPackedContext: PSecBuffer, Token: *mut c_void, phContext: PCtxtHandle,
    ) -> SECURITY_STATUS;
    pub fn ImportSecurityContextW(
        pszPackage: LPWSTR, pPackedContext: PSecBuffer, Token: *mut c_void, phContext: PCtxtHandle,
    ) -> SECURITY_STATUS;
    // pub fn InitSecurityInterfaceA();
    // pub fn InitSecurityInterfaceW();
    pub fn InitializeSecurityContextA(
        phCredential: PCredHandle, phContext: PCtxtHandle, pszTargetName: *mut SEC_CHAR,
        fContextReq: c_ulong, Reserved1: c_ulong, TargetDataRep: c_ulong, pInput: PSecBufferDesc,
        Reserved2: c_ulong, phNewContext: PCtxtHandle, pOutput: PSecBufferDesc,
        pfContextAttr: *mut c_ulong, ptsExpiry: PTimeStamp,
    ) -> SECURITY_STATUS;
    pub fn InitializeSecurityContextW(
        phCredential: PCredHandle, phContext: PCtxtHandle, pszTargetName: *mut SEC_WCHAR,
        fContextReq: c_ulong, Reserved1: c_ulong, TargetDataRep: c_ulong, pInput: PSecBufferDesc,
        Reserved2: c_ulong, phNewContext: PCtxtHandle, pOutput: PSecBufferDesc,
        pfContextAttr: *mut c_ulong, ptsExpiry: PTimeStamp,
    ) -> SECURITY_STATUS;
    // pub fn LsaCallAuthenticationPackage();
    // pub fn LsaConnectUntrusted();
    // pub fn LsaDeregisterLogonProcess();
    // pub fn LsaEnumerateLogonSessions();
    // pub fn LsaFreeReturnBuffer();
    // pub fn LsaGetLogonSessionData();
    // pub fn LsaLogonUser();
    // pub fn LsaLookupAuthenticationPackage();
    // pub fn LsaRegisterLogonProcess();
    // pub fn LsaRegisterPolicyChangeNotification();
    // pub fn LsaUnregisterPolicyChangeNotification();
    pub fn MakeSignature(
        phContext: PCtxtHandle, fQOP: c_ulong, pMessage: PSecBufferDesc, MessageSeqNo: c_ulong,
    ) -> SECURITY_STATUS;
    pub fn QueryContextAttributesA(
        phContext: PCtxtHandle, ulAttribute: c_ulong, pBuffer: *mut c_void,
    -> SECURITY_STATUS;
    pub fn QueryContextAttributesW(
        phContext: PCtxtHandle, ulAttribute: c_ulong, pBuffer: *mut c_void,
    -> SECURITY_STATUS;
    pub fn QueryCredentialsAttributesA(
        phCredential: PCredHandle, ulAttribute: c_ulong, pBuffer: *mut c_void,
    ) -> SECURITY_STATUS;
    pub fn QueryCredentialsAttributesW(
        phCredential: PCredHandle, ulAttribute: c_ulong, pBuffer: *mut c_void,
    ) -> SECURITY_STATUS;
    pub fn QuerySecurityContextToken(
        phContext: PCtxtHandle, Token: *mut *mut c_void,
    ) -> SECURITY_STATUS;
    pub fn QuerySecurityPackageInfoA(
        pszPackageName: LPSTR, ppPackageInfo: *mut PSecPkgInfoA,
    ) -> SECURITY_STATUS;
    pub fn QuerySecurityPackageInfoW(
        pszPackageName: LPWSTR, ppPackageInfo: *mut PSecPkgInfoW,
    ) -> SECURITY_STATUS;
    pub fn RevertSecurityContext(phContext: PCtxtHandle) -> SECURITY_STATUS;
    // pub fn SaslAcceptSecurityContext();
    // pub fn SaslEnumerateProfilesA();
    // pub fn SaslEnumerateProfilesW();
    // pub fn SaslGetContextOption();
    // pub fn SaslGetProfilePackageA();
    // pub fn SaslGetProfilePackageW();
    // pub fn SaslIdentifyPackageA();
    // pub fn SaslIdentifyPackageW();
    // pub fn SaslInitializeSecurityContextA();
    // pub fn SaslInitializeSecurityContextW();
    // pub fn SaslSetContextOption();
    // pub fn SealMessage();
    // pub fn SeciAllocateAndSetCallFlags();
    // pub fn SeciAllocateAndSetIPAddress();
    // pub fn SeciFreeCallContext();
    pub fn SetContextAttributesA(
        phContext: PCtxtHandle, ulAttribute: c_ulong, pBuffer: *mut c_void, cbBuffer: c_ulong,
    ) -> SECURITY_STATUS;
    pub fn SetContextAttributesW(
        phContext: PCtxtHandle, ulAttribute: c_ulong, pBuffer: *mut c_void, cbBuffer: c_ulong,
    ) -> SECURITY_STATUS;
    pub fn SetCredentialsAttributesA(
        phCredential: PCredHandle, ulAttribute: c_ulong, pBuffer: *mut c_void, cbBuffer: c_ulong,
    ) -> SECURITY_STATUS;
    pub fn SetCredentialsAttributesW(
        phCredential: PCredHandle, ulAttribute: c_ulong, pBuffer: *mut c_void, cbBuffer: c_ulong,
    ) -> SECURITY_STATUS;
    // pub fn SspiCompareAuthIdentities();
    // pub fn SspiCopyAuthIdentity();
    // pub fn SspiDecryptAuthIdentity();
    // pub fn SspiEncodeAuthIdentityAsStrings();
    // pub fn SspiEncodeStringsAsAuthIdentity();
    // pub fn SspiEncryptAuthIdentity();
    // pub fn SspiExcludePackage();
    // pub fn SspiFreeAuthIdentity();
    // pub fn SspiGetTargetHostName();
    // pub fn SspiIsAuthIdentityEncrypted();
    // pub fn SspiLocalFree();
    // pub fn SspiMarshalAuthIdentity();
    // pub fn SspiPrepareForCredRead();
    // pub fn SspiPrepareForCredWrite();
    // pub fn SspiUnmarshalAuthIdentity();
    // pub fn SspiValidateAuthIdentity();
    // pub fn SspiZeroAuthIdentity();
    // pub fn TranslateNameA();
    // pub fn TranslateNameW();
    // pub fn UnsealMessage();
    pub fn VerifySignature(
        phContext: PCtxtHandle, pMessage: PSecBufferDesc, MessageSeqNo: c_ulong,
        pfQOP: *mut c_ulong,
    ) -> SECURITY_STATUS;
}
<commit_msg>Fixed build<commit_after>// Copyright © 2015, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
//! FFI bindings to secur32.
#![cfg(windows)]
extern crate winapi;
use winapi::*;
extern "system" {
    pub fn AcceptSecurityContext(
        phCredential: PCredHandle, phContext: PCtxtHandle, pInput: PSecBufferDesc,
        fContextReq: c_ulong, TargetDataRep: c_ulong, phNewContext: PCtxtHandle,
        pOutput: PSecBufferDesc, pfContextAttr: *mut c_ulong, ptsExpiry: PTimeStamp,
    ) -> SECURITY_STATUS;
    pub fn AcquireCredentialsHandleA(
        pszPrincipal: LPSTR, pszPackage: LPSTR, fCredentialUse: c_ulong, pvLogonId: *mut c_void,
        pAuthData: *mut c_void, pGetKeyFn: SEC_GET_KEY_FN, pvGetKeyArgument: *mut c_void,
        phCredential: PCredHandle, ptsExpiry: PTimeStamp,
    ) -> SECURITY_STATUS;
    pub fn AcquireCredentialsHandleW(
        pszPrincipal: LPWSTR, pszPackage: LPWSTR, fCredentialUse: c_ulong, pvLogonId: *mut c_void,
        pAuthData: *mut c_void, pGetKeyFn: SEC_GET_KEY_FN, pvGetKeyArgument: *mut c_void,
        phCredential: PCredHandle, ptsExpiry: PTimeStamp,
    ) -> SECURITY_STATUS;
    pub fn AddCredentialsA(
        hCredentials: PCredHandle, pszPrincipal: LPSTR, pszPackage: LPSTR, fCredentialUse: c_ulong,
        pAuthData: *mut c_void, pGetKeyFn: SEC_GET_KEY_FN, pvGetKeyArgument: *mut c_void,
        ptsExpiry: PTimeStamp,
    ) -> SECURITY_STATUS;
    pub fn AddCredentialsW(
        hCredentials: PCredHandle, pszPrincipal: LPWSTR, pszPackage: LPWSTR,
        fCredentialUse: c_ulong, pAuthData: *mut c_void, pGetKeyFn: SEC_GET_KEY_FN,
        pvGetKeyArgument: *mut c_void, ptsExpiry: PTimeStamp,
    ) -> SECURITY_STATUS;
    // pub fn AddSecurityPackageA();
    // pub fn AddSecurityPackageW();
    pub fn ApplyControlToken(phContext: PCtxtHandle, pInput: PSecBufferDesc) -> SECURITY_STATUS;
    pub fn ChangeAccountPasswordA(
        pszPackageName: *mut SEC_CHAR, pszDomainName: *mut SEC_CHAR, pszAccountName: *mut SEC_CHAR, pszOldPassword: *mut SEC_CHAR, pszNewPassword: *mut SEC_CHAR, bImpersonating: BOOLEAN,
        dwReserved: c_ulong, pOutput: PSecBufferDesc,
    ) -> SECURITY_STATUS;
    pub fn ChangeAccountPasswordW(
        pszPackageName: *mut SEC_WCHAR, pszDomainName: *mut SEC_WCHAR,
        pszAccountName: *mut SEC_WCHAR, pszOldPassword: *mut SEC_WCHAR,
        pszNewPassword: *mut SEC_WCHAR, bImpersonating: BOOLEAN, dwReserved: c_ulong,
        pOutput: PSecBufferDesc,
    ) -> SECURITY_STATUS;
    pub fn CompleteAuthToken(phContext: PCtxtHandle, pToken: PSecBufferDesc) -> SECURITY_STATUS;
    pub fn DecryptMessage(
        phContext: PCtxtHandle, pMessage: PSecBufferDesc, MessageSeqNo: c_ulong,
        pfQOP: *mut c_ulong,
    ) -> SECURITY_STATUS;
    pub fn DeleteSecurityContext(phContext: PCtxtHandle) -> SECURITY_STATUS;
    // pub fn DeleteSecurityPackageA();
    // pub fn DeleteSecurityPackageW();
    pub fn EncryptMessage(
        phContext: PCtxtHandle, fQOP: c_ulong, pMessage: PSecBufferDesc, MessageSeqNo: c_ulong,
    ) -> SECURITY_STATUS;
    pub fn EnumerateSecurityPackagesA(
        pcPackages: *mut c_ulong, ppPackageInfo: *mut PSecPkgInfoA,
    ) -> SECURITY_STATUS;
    pub fn EnumerateSecurityPackagesW(
        pcPackages: *mut c_ulong, ppPackageInfo: *mut PSecPkgInfoW,
    ) -> SECURITY_STATUS;
    pub fn ExportSecurityContext(
        phContext: PCtxtHandle, fFlags: ULONG, pPackedContext: PSecBuffer,
        pToken: *mut *mut c_void,
    ) -> SECURITY_STATUS;
    pub fn FreeContextBuffer(pvContextBuffer: PVOID) -> SECURITY_STATUS;
    pub fn FreeCredentialsHandle(phCredential: PCredHandle) -> SECURITY_STATUS;
    // pub fn GetComputerObjectNameA();
    // pub fn GetComputerObjectNameW();
    // pub fn GetSecurityUserInfo();
    // pub fn GetUserNameExA();
    // pub fn GetUserNameExW();
    pub fn ImpersonateSecurityContext(phContext: PCtxtHandle) -> SECURITY_STATUS;
    pub fn ImportSecurityContextA(
        pszPackage: LPSTR, pPackedContext: PSecBuffer, Token: *mut c_void, phContext: PCtxtHandle,
    ) -> SECURITY_STATUS;
    pub fn ImportSecurityContextW(
        pszPackage: LPWSTR, pPackedContext: PSecBuffer, Token: *mut c_void, phContext: PCtxtHandle,
    ) -> SECURITY_STATUS;
    // pub fn InitSecurityInterfaceA();
    // pub fn InitSecurityInterfaceW();
    pub fn InitializeSecurityContextA(
        phCredential: PCredHandle, phContext: PCtxtHandle, pszTargetName: *mut SEC_CHAR,
        fContextReq: c_ulong, Reserved1: c_ulong, TargetDataRep: c_ulong, pInput: PSecBufferDesc,
        Reserved2: c_ulong, phNewContext: PCtxtHandle, pOutput: PSecBufferDesc,
        pfContextAttr: *mut c_ulong, ptsExpiry: PTimeStamp,
    ) -> SECURITY_STATUS;
    pub fn InitializeSecurityContextW(
        phCredential: PCredHandle, phContext: PCtxtHandle, pszTargetName: *mut SEC_WCHAR,
        fContextReq: c_ulong, Reserved1: c_ulong, TargetDataRep: c_ulong, pInput: PSecBufferDesc,
        Reserved2: c_ulong, phNewContext: PCtxtHandle, pOutput: PSecBufferDesc,
        pfContextAttr: *mut c_ulong, ptsExpiry: PTimeStamp,
    ) -> SECURITY_STATUS;
    // pub fn LsaCallAuthenticationPackage();
    // pub fn LsaConnectUntrusted();
    // pub fn LsaDeregisterLogonProcess();
    // pub fn LsaEnumerateLogonSessions();
    // pub fn LsaFreeReturnBuffer();
    // pub fn LsaGetLogonSessionData();
    // pub fn LsaLogonUser();
    // pub fn LsaLookupAuthenticationPackage();
    // pub fn LsaRegisterLogonProcess();
    // pub fn LsaRegisterPolicyChangeNotification();
    // pub fn LsaUnregisterPolicyChangeNotification();
    pub fn MakeSignature(
        phContext: PCtxtHandle, fQOP: c_ulong, pMessage: PSecBufferDesc, MessageSeqNo: c_ulong,
    ) -> SECURITY_STATUS;
    pub fn QueryContextAttributesA(
        phContext: PCtxtHandle, ulAttribute: c_ulong, pBuffer: *mut c_void,
    ) -> SECURITY_STATUS;
    pub fn QueryContextAttributesW(
        phContext: PCtxtHandle, ulAttribute: c_ulong, pBuffer: *mut c_void,
    ) -> SECURITY_STATUS;
    pub fn QueryCredentialsAttributesA(
        phCredential: PCredHandle, ulAttribute: c_ulong, pBuffer: *mut c_void,
    ) -> SECURITY_STATUS;
    pub fn QueryCredentialsAttributesW(
        phCredential: PCredHandle, ulAttribute: c_ulong, pBuffer: *mut c_void,
    ) -> SECURITY_STATUS;
    pub fn QuerySecurityContextToken(
        phContext: PCtxtHandle, Token: *mut *mut c_void,
    ) -> SECURITY_STATUS;
    pub fn QuerySecurityPackageInfoA(
        pszPackageName: LPSTR, ppPackageInfo: *mut PSecPkgInfoA,
    ) -> SECURITY_STATUS;
    pub fn QuerySecurityPackageInfoW(
        pszPackageName: LPWSTR, ppPackageInfo: *mut PSecPkgInfoW,
    ) -> SECURITY_STATUS;
    pub fn RevertSecurityContext(phContext: PCtxtHandle) -> SECURITY_STATUS;
    // pub fn SaslAcceptSecurityContext();
    // pub fn SaslEnumerateProfilesA();
    // pub fn SaslEnumerateProfilesW();
    // pub fn SaslGetContextOption();
    // pub fn SaslGetProfilePackageA();
    // pub fn SaslGetProfilePackageW();
    // pub fn SaslIdentifyPackageA();
    // pub fn SaslIdentifyPackageW();
    // pub fn SaslInitializeSecurityContextA();
    // pub fn SaslInitializeSecurityContextW();
    // pub fn SaslSetContextOption();
    // pub fn SealMessage();
    // pub fn SeciAllocateAndSetCallFlags();
    // pub fn SeciAllocateAndSetIPAddress();
    // pub fn SeciFreeCallContext();
    pub fn SetContextAttributesA(
        phContext: PCtxtHandle, ulAttribute: c_ulong, pBuffer: *mut c_void, cbBuffer: c_ulong,
    ) -> SECURITY_STATUS;
    pub fn SetContextAttributesW(
        phContext: PCtxtHandle, ulAttribute: c_ulong, pBuffer: *mut c_void, cbBuffer: c_ulong,
    ) -> SECURITY_STATUS;
    pub fn SetCredentialsAttributesA(
        phCredential: PCredHandle, ulAttribute: c_ulong, pBuffer: *mut c_void, cbBuffer: c_ulong,
    ) -> SECURITY_STATUS;
    pub fn SetCredentialsAttributesW(
        phCredential: PCredHandle, ulAttribute: c_ulong, pBuffer: *mut c_void, cbBuffer: c_ulong,
    ) -> SECURITY_STATUS;
    // pub fn SspiCompareAuthIdentities();
    // pub fn SspiCopyAuthIdentity();
    // pub fn SspiDecryptAuthIdentity();
    // pub fn SspiEncodeAuthIdentityAsStrings();
    // pub fn SspiEncodeStringsAsAuthIdentity();
    // pub fn SspiEncryptAuthIdentity();
    // pub fn SspiExcludePackage();
    // pub fn SspiFreeAuthIdentity();
    // pub fn SspiGetTargetHostName();
    // pub fn SspiIsAuthIdentityEncrypted();
    // pub fn SspiLocalFree();
    // pub fn SspiMarshalAuthIdentity();
    // pub fn SspiPrepareForCredRead();
    // pub fn SspiPrepareForCredWrite();
    // pub fn SspiUnmarshalAuthIdentity();
    // pub fn SspiValidateAuthIdentity();
    // pub fn SspiZeroAuthIdentity();
    // pub fn TranslateNameA();
    // pub fn TranslateNameW();
    // pub fn UnsealMessage();
    pub fn VerifySignature(
        phContext: PCtxtHandle, pMessage: PSecBufferDesc, MessageSeqNo: c_ulong,
        pfQOP: *mut c_ulong,
    ) -> SECURITY_STATUS;
}
<|endoftext|>