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

/*!
A mini version of ast::Ty, which is easier to use, and features an
explicit `Self` type to use when specifying impls to be derived.
*/

use ast;
use ast::{P,Expr,Generics,Ident};
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use codemap::{Span,respan};
use owned_slice::OwnedSlice;
use parse::token::special_idents;

use std::gc::Gc;

/// The types of pointers
pub enum PtrTy<'a> {
    /// &'lifetime mut
    Borrowed(Option<&'a str>, ast::Mutability),
}

/// A path, e.g. `::std::option::Option::<int>` (global). Has support
/// for type parameters and a lifetime.
pub struct Path<'a> {
    pub path: Vec<&'a str> ,
    pub lifetime: Option<&'a str>,
    pub params: Vec<Box<Ty<'a>>>,
    pub global: bool,
}

impl<'a> Path<'a> {
    pub fn new<'r>(path: Vec<&'r str> ) -> Path<'r> {
        Path::new_(path, None, Vec::new(), true)
    }
    pub fn new_local<'r>(path: &'r str) -> Path<'r> {
        Path::new_(vec!( path ), None, Vec::new(), false)
    }
    pub fn new_<'r>(path: Vec<&'r str> ,
                    lifetime: Option<&'r str>,
                    params: Vec<Box<Ty<'r>>>,
                    global: bool)
                    -> Path<'r> {
        Path {
            path: path,
            lifetime: lifetime,
            params: params,
            global: global
        }
    }

    pub fn to_ty(&self,
                 cx: &ExtCtxt,
                 span: Span,
                 self_ty: Ident,
                 self_generics: &Generics)
                 -> P<ast::Ty> {
        cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None)
    }
    pub fn to_path(&self,
                   cx: &ExtCtxt,
                   span: Span,
                   self_ty: Ident,
                   self_generics: &Generics)
                   -> ast::Path {
        let idents = self.path.iter().map(|s| cx.ident_of(*s)).collect();
        let lt = mk_lifetimes(cx, span, &self.lifetime);
        let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();

        cx.path_all(span, self.global, idents, lt, tys)
    }
}

/// A type. Supports pointers (except for *), Self, and literals
pub enum Ty<'a> {
    Self,
    /// &/Box/ Ty
    Ptr(Box<Ty<'a>>, PtrTy<'a>),
    /// mod::mod::Type<[lifetime], [Params...]>, including a plain type
    /// parameter, and things like `int`
    Literal(Path<'a>),
    /// includes unit
    Tuple(Vec<Ty<'a>> )
}

pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
    Borrowed(None, ast::MutImmutable)
}
pub fn borrowed<'r>(ty: Box<Ty<'r>>) -> Ty<'r> {
    Ptr(ty, borrowed_ptrty())
}

pub fn borrowed_explicit_self<'r>() -> Option<Option<PtrTy<'r>>> {
    Some(Some(borrowed_ptrty()))
}

pub fn borrowed_self<'r>() -> Ty<'r> {
    borrowed(box Self)
}

pub fn nil_ty() -> Ty<'static> {
    Tuple(Vec::new())
}

fn mk_lifetime(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Option<ast::Lifetime> {
    match *lt {
        Some(ref s) => Some(cx.lifetime(span, cx.ident_of(*s).name)),
        None => None
    }
}

fn mk_lifetimes(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Vec<ast::Lifetime> {
    match *lt {
        Some(ref s) => vec!(cx.lifetime(span, cx.ident_of(*s).name)),
        None => vec!()
    }
}

impl<'a> Ty<'a> {
    pub fn to_ty(&self,
                 cx: &ExtCtxt,
                 span: Span,
                 self_ty: Ident,
                 self_generics: &Generics)
                 -> P<ast::Ty> {
        match *self {
            Ptr(ref ty, ref ptr) => {
                let raw_ty = ty.to_ty(cx, span, self_ty, self_generics);
                match *ptr {
                    Borrowed(ref lt, mutbl) => {
                        let lt = mk_lifetime(cx, span, lt);
                        cx.ty_rptr(span, raw_ty, lt, mutbl)
                    }
                }
            }
            Literal(ref p) => { p.to_ty(cx, span, self_ty, self_generics) }
            Self  => {
                cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None)
            }
            Tuple(ref fields) => {
                let ty = if fields.is_empty() {
                    ast::TyNil
                } else {
                    ast::TyTup(fields.iter()
                                     .map(|f| f.to_ty(cx, span, self_ty, self_generics))
                                     .collect())
                };

                cx.ty(span, ty)
            }
        }
    }

    pub fn to_path(&self,
                   cx: &ExtCtxt,
                   span: Span,
                   self_ty: Ident,
                   self_generics: &Generics)
                   -> ast::Path {
        match *self {
            Self => {
                let self_params = self_generics.ty_params.map(|ty_param| {
                    cx.ty_ident(span, ty_param.ident)
                });
                let lifetimes = self_generics.lifetimes.clone();

                cx.path_all(span, false, vec!(self_ty), lifetimes,
                            self_params.into_vec())
            }
            Literal(ref p) => {
                p.to_path(cx, span, self_ty, self_generics)
            }
            Ptr(..) => { cx.span_bug(span, "pointer in a path in generic `deriving`") }
            Tuple(..) => { cx.span_bug(span, "tuple in a path in generic `deriving`") }
        }
    }
}

fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str,
               bounds: &[Path], unbound: Option<ast::TyParamBound>,
               self_ident: Ident, self_generics: &Generics) -> ast::TyParam {
    let bounds =
        bounds.iter().map(|b| {
            let path = b.to_path(cx, span, self_ident, self_generics);
            cx.typarambound(path)
        }).collect();
    cx.typaram(span, cx.ident_of(name), bounds, unbound, None)
}

fn mk_generics(lifetimes: Vec<ast::Lifetime>, ty_params: Vec<ast::TyParam> ) -> Generics {
    Generics {
        lifetimes: lifetimes,
        ty_params: OwnedSlice::from_vec(ty_params)
    }
}

/// Lifetimes and bounds on type parameters
pub struct LifetimeBounds<'a> {
    pub lifetimes: Vec<&'a str>,
    pub bounds: Vec<(&'a str, Option<ast::TyParamBound>, Vec<Path<'a>>)>,
}

impl<'a> LifetimeBounds<'a> {
    pub fn empty() -> LifetimeBounds<'static> {
        LifetimeBounds {
            lifetimes: Vec::new(), bounds: Vec::new()
        }
    }
    pub fn to_generics(&self,
                       cx: &ExtCtxt,
                       span: Span,
                       self_ty: Ident,
                       self_generics: &Generics)
                       -> Generics {
        let lifetimes = self.lifetimes.iter().map(|lt| {
            cx.lifetime(span, cx.ident_of(*lt).name)
        }).collect();
        let ty_params = self.bounds.iter().map(|t| {
            match t {
                &(ref name, ref unbound, ref bounds) => {
                    mk_ty_param(cx,
                                span,
                                *name,
                                bounds.as_slice(),
                                unbound.clone(),
                                self_ty,
                                self_generics)
                }
            }
        }).collect();
        mk_generics(lifetimes, ty_params)
    }
}

pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
    -> (Gc<Expr>, ast::ExplicitSelf) {
    // this constructs a fresh `self` path, which will match the fresh `self` binding
    // created below.
    let self_path = cx.expr_self(span);
    match *self_ptr {
        None => {
            (self_path, respan(span, ast::SelfValue(special_idents::self_)))
        }
        Some(ref ptr) => {
            let self_ty = respan(
                span,
                match *ptr {
                    Borrowed(ref lt, mutbl) => {
                        let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s).name));
                        ast::SelfRegion(lt, mutbl, special_idents::self_)
                    }
                });
            let self_expr = cx.expr_deref(span, self_path);
            (self_expr, self_ty)
        }
    }
}
<commit_msg>auto merge of #15814 : kvark/rust/ast, r=huonw<commit_after>// Copyright 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.

/*!
A mini version of ast::Ty, which is easier to use, and features an
explicit `Self` type to use when specifying impls to be derived.
*/

use ast;
use ast::{P,Expr,Generics,Ident};
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use codemap::{Span,respan};
use owned_slice::OwnedSlice;
use parse::token::special_idents;

use std::gc::Gc;

/// The types of pointers
#[deriving(Clone)]
pub enum PtrTy<'a> {
    /// &'lifetime mut
    Borrowed(Option<&'a str>, ast::Mutability),
}

/// A path, e.g. `::std::option::Option::<int>` (global). Has support
/// for type parameters and a lifetime.
#[deriving(Clone)]
pub struct Path<'a> {
    pub path: Vec<&'a str> ,
    pub lifetime: Option<&'a str>,
    pub params: Vec<Box<Ty<'a>>>,
    pub global: bool,
}

impl<'a> Path<'a> {
    pub fn new<'r>(path: Vec<&'r str> ) -> Path<'r> {
        Path::new_(path, None, Vec::new(), true)
    }
    pub fn new_local<'r>(path: &'r str) -> Path<'r> {
        Path::new_(vec!( path ), None, Vec::new(), false)
    }
    pub fn new_<'r>(path: Vec<&'r str> ,
                    lifetime: Option<&'r str>,
                    params: Vec<Box<Ty<'r>>>,
                    global: bool)
                    -> Path<'r> {
        Path {
            path: path,
            lifetime: lifetime,
            params: params,
            global: global
        }
    }

    pub fn to_ty(&self,
                 cx: &ExtCtxt,
                 span: Span,
                 self_ty: Ident,
                 self_generics: &Generics)
                 -> P<ast::Ty> {
        cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None)
    }
    pub fn to_path(&self,
                   cx: &ExtCtxt,
                   span: Span,
                   self_ty: Ident,
                   self_generics: &Generics)
                   -> ast::Path {
        let idents = self.path.iter().map(|s| cx.ident_of(*s)).collect();
        let lt = mk_lifetimes(cx, span, &self.lifetime);
        let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();

        cx.path_all(span, self.global, idents, lt, tys)
    }
}

/// A type. Supports pointers (except for *), Self, and literals
#[deriving(Clone)]
pub enum Ty<'a> {
    Self,
    /// &/Box/ Ty
    Ptr(Box<Ty<'a>>, PtrTy<'a>),
    /// mod::mod::Type<[lifetime], [Params...]>, including a plain type
    /// parameter, and things like `int`
    Literal(Path<'a>),
    /// includes unit
    Tuple(Vec<Ty<'a>> )
}

pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
    Borrowed(None, ast::MutImmutable)
}
pub fn borrowed<'r>(ty: Box<Ty<'r>>) -> Ty<'r> {
    Ptr(ty, borrowed_ptrty())
}

pub fn borrowed_explicit_self<'r>() -> Option<Option<PtrTy<'r>>> {
    Some(Some(borrowed_ptrty()))
}

pub fn borrowed_self<'r>() -> Ty<'r> {
    borrowed(box Self)
}

pub fn nil_ty<'r>() -> Ty<'r> {
    Tuple(Vec::new())
}

fn mk_lifetime(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Option<ast::Lifetime> {
    match *lt {
        Some(ref s) => Some(cx.lifetime(span, cx.ident_of(*s).name)),
        None => None
    }
}

fn mk_lifetimes(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Vec<ast::Lifetime> {
    match *lt {
        Some(ref s) => vec!(cx.lifetime(span, cx.ident_of(*s).name)),
        None => vec!()
    }
}

impl<'a> Ty<'a> {
    pub fn to_ty(&self,
                 cx: &ExtCtxt,
                 span: Span,
                 self_ty: Ident,
                 self_generics: &Generics)
                 -> P<ast::Ty> {
        match *self {
            Ptr(ref ty, ref ptr) => {
                let raw_ty = ty.to_ty(cx, span, self_ty, self_generics);
                match *ptr {
                    Borrowed(ref lt, mutbl) => {
                        let lt = mk_lifetime(cx, span, lt);
                        cx.ty_rptr(span, raw_ty, lt, mutbl)
                    }
                }
            }
            Literal(ref p) => { p.to_ty(cx, span, self_ty, self_generics) }
            Self  => {
                cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None)
            }
            Tuple(ref fields) => {
                let ty = if fields.is_empty() {
                    ast::TyNil
                } else {
                    ast::TyTup(fields.iter()
                                     .map(|f| f.to_ty(cx, span, self_ty, self_generics))
                                     .collect())
                };

                cx.ty(span, ty)
            }
        }
    }

    pub fn to_path(&self,
                   cx: &ExtCtxt,
                   span: Span,
                   self_ty: Ident,
                   self_generics: &Generics)
                   -> ast::Path {
        match *self {
            Self => {
                let self_params = self_generics.ty_params.map(|ty_param| {
                    cx.ty_ident(span, ty_param.ident)
                });
                let lifetimes = self_generics.lifetimes.clone();

                cx.path_all(span, false, vec!(self_ty), lifetimes,
                            self_params.into_vec())
            }
            Literal(ref p) => {
                p.to_path(cx, span, self_ty, self_generics)
            }
            Ptr(..) => { cx.span_bug(span, "pointer in a path in generic `deriving`") }
            Tuple(..) => { cx.span_bug(span, "tuple in a path in generic `deriving`") }
        }
    }
}

fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str,
               bounds: &[Path], unbound: Option<ast::TyParamBound>,
               self_ident: Ident, self_generics: &Generics) -> ast::TyParam {
    let bounds =
        bounds.iter().map(|b| {
            let path = b.to_path(cx, span, self_ident, self_generics);
            cx.typarambound(path)
        }).collect();
    cx.typaram(span, cx.ident_of(name), bounds, unbound, None)
}

fn mk_generics(lifetimes: Vec<ast::Lifetime>, ty_params: Vec<ast::TyParam> ) -> Generics {
    Generics {
        lifetimes: lifetimes,
        ty_params: OwnedSlice::from_vec(ty_params)
    }
}

/// Lifetimes and bounds on type parameters
#[deriving(Clone)]
pub struct LifetimeBounds<'a> {
    pub lifetimes: Vec<&'a str>,
    pub bounds: Vec<(&'a str, Option<ast::TyParamBound>, Vec<Path<'a>>)>,
}

impl<'a> LifetimeBounds<'a> {
    pub fn empty() -> LifetimeBounds<'a> {
        LifetimeBounds {
            lifetimes: Vec::new(), bounds: Vec::new()
        }
    }
    pub fn to_generics(&self,
                       cx: &ExtCtxt,
                       span: Span,
                       self_ty: Ident,
                       self_generics: &Generics)
                       -> Generics {
        let lifetimes = self.lifetimes.iter().map(|lt| {
            cx.lifetime(span, cx.ident_of(*lt).name)
        }).collect();
        let ty_params = self.bounds.iter().map(|t| {
            match t {
                &(ref name, ref unbound, ref bounds) => {
                    mk_ty_param(cx,
                                span,
                                *name,
                                bounds.as_slice(),
                                unbound.clone(),
                                self_ty,
                                self_generics)
                }
            }
        }).collect();
        mk_generics(lifetimes, ty_params)
    }
}

pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
    -> (Gc<Expr>, ast::ExplicitSelf) {
    // this constructs a fresh `self` path, which will match the fresh `self` binding
    // created below.
    let self_path = cx.expr_self(span);
    match *self_ptr {
        None => {
            (self_path, respan(span, ast::SelfValue(special_idents::self_)))
        }
        Some(ref ptr) => {
            let self_ty = respan(
                span,
                match *ptr {
                    Borrowed(ref lt, mutbl) => {
                        let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s).name));
                        ast::SelfRegion(lt, mutbl, special_idents::self_)
                    }
                });
            let self_expr = cx.expr_deref(span, self_path);
            (self_expr, self_ty)
        }
    }
}
<|endoftext|>


<commit_before>//! Defines errors which may be returned by [sharedlib](index.html).

use std::io;
use std::path::PathBuf;
use string::error::library_close as library_close_string;
use string::error::library_find_symbol as library_find_symbol_string;
use string::error::library_open as library_open_string;
use string::error::os_error as os_error_string;
use string::error::os_error_failure as os_error_failure_string;

error_chain! {
    types { }

    links { }

    foreign_links {
        io::Error, IoError;
    }

    errors {
        LibraryClose {
            description(library_close_string::description())
            display(
                "{}",
                library_close_string::display_1()
            )
        }

        LibraryFindSymbol(symbol: String) {
            description(library_find_symbol_string::description())
            display(
                "{}{}{}",
                library_find_symbol_string::display_1(),
                symbol,
                library_find_symbol_string::display_2()
            )
        }

        LibraryOpen(path_to_lib: PathBuf) {
            description(library_open_string::description())
            display(
                "{}{}{}",
                library_open_string::display_1(),
                path_to_lib.to_string_lossy(),
                library_open_string::display_2()
            )
        }

        OsError(cause: String, function_called: String) {
            description(os_error_string::description())
            display(
                "{}{}{}{}",
                os_error_string::display_1(),
                function_called,
                os_error_string::display_2(),
                cause
            )
        }

        OsErrorFailure(function_called: String) {
            description(os_error_failure_string::description())
            display(
                "{}{}{}",
                os_error_failure_string::display_1(),
                function_called,
                os_error_failure_string::display_2()
            )
        }
    }
}
<commit_msg>Removed unnecessary foreign link.<commit_after>//! Defines errors which may be returned by [sharedlib](index.html).

use std::path::PathBuf;
use string::error::library_close as library_close_string;
use string::error::library_find_symbol as library_find_symbol_string;
use string::error::library_open as library_open_string;
use string::error::os_error as os_error_string;
use string::error::os_error_failure as os_error_failure_string;

error_chain! {
    types { }

    links { }

    foreign_links { }

    errors {
        LibraryClose {
            description(library_close_string::description())
            display(
                "{}",
                library_close_string::display_1()
            )
        }

        LibraryFindSymbol(symbol: String) {
            description(library_find_symbol_string::description())
            display(
                "{}{}{}",
                library_find_symbol_string::display_1(),
                symbol,
                library_find_symbol_string::display_2()
            )
        }

        LibraryOpen(path_to_lib: PathBuf) {
            description(library_open_string::description())
            display(
                "{}{}{}",
                library_open_string::display_1(),
                path_to_lib.to_string_lossy(),
                library_open_string::display_2()
            )
        }

        OsError(cause: String, function_called: String) {
            description(os_error_string::description())
            display(
                "{}{}{}{}",
                os_error_string::display_1(),
                function_called,
                os_error_string::display_2(),
                cause
            )
        }

        OsErrorFailure(function_called: String) {
            description(os_error_failure_string::description())
            display(
                "{}{}{}",
                os_error_failure_string::display_1(),
                function_called,
                os_error_failure_string::display_2()
            )
        }
    }
}
<|endoftext|>


<commit_before>use session::*;

pub struct HandshakeNN {
    session: Session,
    state: usize
}

impl HandshakeNN {
    pub fn new() -> HandshakeNN {
        HandshakeNN {
            session: Session::new(None, None),
            state: 0
        }
    }

    fn descriptor(&self) -> &'static [Descriptor] {
        static DESCS: &'static [&'static [Descriptor]] = &[
            &[Descriptor::Ephemeral],
            &[Descriptor::Ephemeral, Descriptor::DHEE]
        ];
        DESCS[self.state]
    }

    pub fn send(&mut self) -> Vec<u8> {
        let desc = self.descriptor();
        let msg = self.session.create(&[], desc, &[]);
        self.state += 1;
        msg
    }

    pub fn recv(&mut self, msg: &[u8]) -> Result<bool,()> {
        let desc = self.descriptor();
        try!(self.session.consume(msg, desc));
        self.state += 1;
        Ok(self.state > 1)
    }

    pub fn finish(mut self) -> (Session, Session) {
        let mut first = self.session.derive();
        let second = first.derive();
        (first, second)
    }
}

#[test]
fn test_handshakeNN() {
    let mut client = HandshakeNN::new();
    let mut server = HandshakeNN::new();

    server.recv(&client.send()[..]).unwrap();
    client.recv(&server.send()[..]).unwrap();
    let (c1, c2) = client.finish();
    let (s1, s2) = server.finish();
    assert!(c1.k.unwrap().0 == s1.k.unwrap().0);
    assert!(c2.k.unwrap().0 == s2.k.unwrap().0);
    assert!(&c1.h.0[..] == &s1.h.0[..]);
    assert!(&c2.h.0[..] == &s2.h.0[..]);
}

/*
client flow:

let hs = HandshakeNN::new();
socket.send(hs.send());
hs.recv(socket.recv());
let (send, recv) = hs.finish();

server flow:

let hs = HandshakeNN::new();
hs.recv(socket.recv());
socket.send(hs.send());
let (recv, send) = hs.finish();
*/
<commit_msg>Abstract Handshake, add HandshakeXX<commit_after>use session::*;

pub struct Handshake {
    session: Session,
    state: usize,
    descriptors: &'static [&'static [Descriptor]],
}

impl Handshake {
    pub fn new(local: Option<KeyPair>, remote: Option<PubKey>, descriptors: &'static [&'static [Descriptor]]) -> Handshake {
        Handshake {
            session: Session::new(local, remote),
            state: 0,
            descriptors: descriptors
        }
    }
    fn descriptor(&self) -> &'static [Descriptor] {
        self.descriptors[self.state]
    }
    fn next_state(&mut self) -> bool {
        self.state += 1;
        self.state >= self.descriptors.len()
    }

    pub fn send(&mut self) -> Vec<u8> {
        let desc = self.descriptor();
        let msg = self.session.create(&[], desc, &[]);
        self.next_state();
        msg
    }

    pub fn recv(&mut self, msg: &[u8]) -> Result<bool,()> {
        let desc = self.descriptor();
        try!(self.session.consume(msg, desc));
        Ok(self.next_state())
    }

    pub fn finish(mut self) -> (Session, Session) {
        let mut first = self.session.derive();
        let second = first.derive();
        (first, second)
    }
}

pub struct HandshakeNN;

impl HandshakeNN {
    pub fn new() -> Handshake {
        static DESCS: &'static [&'static [Descriptor]] = &[
            &[Descriptor::Ephemeral],
            &[Descriptor::Ephemeral, Descriptor::DHEE]
        ];
        Handshake::new(None, None, DESCS)
    }
}

#[test]
fn test_handshakeNN() {
    let mut client = HandshakeNN::new();
    let mut server = HandshakeNN::new();

    server.recv(&client.send()[..]).unwrap();
    client.recv(&server.send()[..]).unwrap();
    let (c1, c2) = client.finish();
    let (s1, s2) = server.finish();
    assert!(c1.k.unwrap().0 == s1.k.unwrap().0);
    assert!(c2.k.unwrap().0 == s2.k.unwrap().0);
    assert!(&c1.h.0[..] == &s1.h.0[..]);
    assert!(&c2.h.0[..] == &s2.h.0[..]);
}

pub struct HandshakeXX;

impl HandshakeXX {
    pub fn new(local: KeyPair) -> Handshake {
        static DESCS: &'static [&'static [Descriptor]] = &[
            &[Descriptor::Ephemeral],
            &[Descriptor::Ephemeral, Descriptor::DHEE, Descriptor::Static, Descriptor::DHSE],
            &[Descriptor::Static, Descriptor::DHSE]
        ];
        Handshake::new(Some(local), None, DESCS)
    }
}

#[test]
fn test_handshakeXX() {
    let mut client = HandshakeXX::new(gen_keypair());
    let mut server = HandshakeXX::new(gen_keypair());

    server.recv(&client.send()[..]).unwrap();
    client.recv(&server.send()[..]).unwrap();
    server.recv(&client.send()[..]).unwrap();
    let (c1, c2) = client.finish();
    let (s1, s2) = server.finish();
    assert!(c1.k.unwrap().0 == s1.k.unwrap().0);
    assert!(c2.k.unwrap().0 == s2.k.unwrap().0);
    assert!(&c1.h.0[..] == &s1.h.0[..]);
    assert!(&c2.h.0[..] == &s2.h.0[..]);
}
<|endoftext|>


<commit_before>use proc_macro2::{Ident, Span};
use std::fmt;

/// Specialized formatting trait used by `format_ident!`.
///
/// [`Ident`] arguments formatted using this trait will have their `r#` prefix
/// stripped, if present.
///
/// See [`format_ident!`] for more information.
pub trait IdentFragment {
    /// Format this value as an identifier fragment.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;

    /// Span associated with this `IdentFragment`.
    ///
    /// If non-`None`, may be inherited by formatted identifiers.
    fn span(&self) -> Option<Span> {
        None
    }
}

impl<T: IdentFragment + ?Sized> IdentFragment for &T {
    fn span(&self) -> Option<Span> {
        <T as IdentFragment>::span(*self)
    }

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        IdentFragment::fmt(*self, f)
    }
}

impl<T: IdentFragment + ?Sized> IdentFragment for &mut T {
    fn span(&self) -> Option<Span> {
        <T as IdentFragment>::span(*self)
    }

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        IdentFragment::fmt(*self, f)
    }
}

impl IdentFragment for Ident {
    fn span(&self) -> Option<Span> {
        Some(self.span())
    }

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let id = self.to_string();
        if id.starts_with("r#") {
            fmt::Display::fmt(&id[2..], f)
        } else {
            fmt::Display::fmt(&id[..], f)
        }
    }
}

// Limited set of types which this is implemented for, as we want to avoid types
// which will often include non-identifier characters in their `Display` impl.
macro_rules! ident_fragment_display {
    ($($T:ty),*) => {
        $(
            impl IdentFragment for $T {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    fmt::Display::fmt(self, f)
                }
            }
        )*
    }
}

ident_fragment_display!(bool, str, String, char);
ident_fragment_display!(u8, u16, u32, u64, u128, usize);
<commit_msg>Implement IdentFragment for Cow<T><commit_after>use proc_macro2::{Ident, Span};
use std::fmt;

/// Specialized formatting trait used by `format_ident!`.
///
/// [`Ident`] arguments formatted using this trait will have their `r#` prefix
/// stripped, if present.
///
/// See [`format_ident!`] for more information.
pub trait IdentFragment {
    /// Format this value as an identifier fragment.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;

    /// Span associated with this `IdentFragment`.
    ///
    /// If non-`None`, may be inherited by formatted identifiers.
    fn span(&self) -> Option<Span> {
        None
    }
}

impl<T: IdentFragment + ?Sized> IdentFragment for &T {
    fn span(&self) -> Option<Span> {
        <T as IdentFragment>::span(*self)
    }

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        IdentFragment::fmt(*self, f)
    }
}

impl<T: IdentFragment + ?Sized> IdentFragment for &mut T {
    fn span(&self) -> Option<Span> {
        <T as IdentFragment>::span(*self)
    }

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        IdentFragment::fmt(*self, f)
    }
}

impl IdentFragment for Ident {
    fn span(&self) -> Option<Span> {
        Some(self.span())
    }

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let id = self.to_string();
        if id.starts_with("r#") {
            fmt::Display::fmt(&id[2..], f)
        } else {
            fmt::Display::fmt(&id[..], f)
        }
    }
}

impl<T: IdentFragment + Clone> IdentFragment for std::borrow::Cow<'_, T> {
    fn span(&self) -> Option<Span> {
        T::span(&self)
    }

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        T::fmt(&self, f)
    }
}

// Limited set of types which this is implemented for, as we want to avoid types
// which will often include non-identifier characters in their `Display` impl.
macro_rules! ident_fragment_display {
    ($($T:ty),*) => {
        $(
            impl IdentFragment for $T {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    fmt::Display::fmt(self, f)
                }
            }
        )*
    }
}

ident_fragment_display!(bool, str, String, char);
ident_fragment_display!(u8, u16, u32, u64, u128, usize);
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A generic, safe mechanism by which DOM objects can be pinned and transferred
//! between threads (or intra-thread for asynchronous events). Akin to Gecko's
//! nsMainThreadPtrHandle, this uses thread-safe reference counting and ensures
//! that the actual SpiderMonkey GC integration occurs on the script thread via
//! weak refcounts. Ownership of a `Trusted<T>` object means the DOM object of
//! type T to which it points remains alive. Any other behaviour is undefined.
//! To guarantee the lifetime of a DOM object when performing asynchronous operations,
//! obtain a `Trusted<T>` from that object and pass it along with each operation.
//! A usable pointer to the original DOM object can be obtained on the script thread
//! from a `Trusted<T>` via the `to_temporary` method.
//!
//! The implementation of `Trusted<T>` is as follows:
//! The `Trusted<T>` object contains an atomic reference counted pointer to the Rust DOM object.
//! A hashtable resides in the script thread, keyed on the pointer.
//! The values in this hashtable are weak reference counts. When a `Trusted<T>` object is
//! created or cloned, the reference count is increased. When a `Trusted<T>` is dropped, the count
//! decreases. If the count hits zero, the weak reference is emptied, and is removed from
//! its hash table during the next GC. During GC, the entries of the hash table are counted
//! as JS roots.

use core::nonzero::NonZero;
use dom::bindings::conversions::ToJSValConvertible;
use dom::bindings::error::Error;
use dom::bindings::js::Root;
use dom::bindings::reflector::{DomObject, Reflector};
use dom::bindings::trace::trace_reflector;
use dom::promise::Promise;
use js::jsapi::JSAutoCompartment;
use js::jsapi::JSTracer;
use libc;
use script_thread::Runnable;
use script_thread::ScriptThread;
use std::cell::RefCell;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::hash_map::HashMap;
use std::hash::Hash;
use std::marker::PhantomData;
use std::os;
use std::rc::Rc;
use std::sync::{Arc, Weak};

#[allow(missing_docs)]  // FIXME
mod dummy {  // Attributes don’t apply through the macro.
    use std::cell::RefCell;
    use std::rc::Rc;
    use super::LiveDOMReferences;
    thread_local!(pub static LIVE_REFERENCES: Rc<RefCell<Option<LiveDOMReferences>>> =
            Rc::new(RefCell::new(None)));
}
pub use self::dummy::LIVE_REFERENCES;

/// A pointer to a Rust DOM object that needs to be destroyed.
pub struct TrustedReference(*const libc::c_void);
unsafe impl Send for TrustedReference {}

impl TrustedReference {
    fn new<T: DomObject>(ptr: *const T) -> TrustedReference {
        TrustedReference(ptr as *const libc::c_void)
    }
}

/// A safe wrapper around a DOM Promise object that can be shared among threads for use
/// in asynchronous operations. The underlying DOM object is guaranteed to live at least
/// as long as the last outstanding `TrustedPromise` instance. These values cannot be cloned,
/// only created from existing Rc<Promise> values.
pub struct TrustedPromise {
    dom_object: *const Promise,
    owner_thread: *const libc::c_void,
}

unsafe impl Send for TrustedPromise {}

impl TrustedPromise {
    /// Create a new `TrustedPromise` instance from an existing DOM object. The object will
    /// be prevented from being GCed for the duration of the resulting `TrustedPromise` object's
    /// lifetime.
    #[allow(unrooted_must_root)]
    pub fn new(promise: Rc<Promise>) -> TrustedPromise {
        LIVE_REFERENCES.with(|ref r| {
            let r = r.borrow();
            let live_references = r.as_ref().unwrap();
            let ptr = &*promise as *const Promise;
            live_references.addref_promise(promise);
            TrustedPromise {
                dom_object: ptr,
                owner_thread: (&*live_references) as *const _ as *const libc::c_void,
            }
        })
    }

    /// Obtain a usable DOM Promise from a pinned `TrustedPromise` value. Fails if used on
    /// a different thread than the original value from which this `TrustedPromise` was
    /// obtained.
    #[allow(unrooted_must_root)]
    pub fn root(self) -> Rc<Promise> {
        LIVE_REFERENCES.with(|ref r| {
            let r = r.borrow();
            let live_references = r.as_ref().unwrap();
            assert!(self.owner_thread == (&*live_references) as *const _ as *const libc::c_void);
            // Borrow-check error requires the redundant `let promise = ...; promise` here.
            let promise = match live_references.promise_table.borrow_mut().entry(self.dom_object) {
                Occupied(mut entry) => {
                    let promise = {
                        let promises = entry.get_mut();
                        promises.pop().expect("rooted promise list unexpectedly empty")
                    };
                    if entry.get().is_empty() {
                        entry.remove();
                    }
                    promise
                }
                Vacant(_) => unreachable!(),
            };
            promise
        })
    }

    /// A runnable which will reject the promise.
    #[allow(unrooted_must_root)]
    pub fn reject_runnable(self, error: Error) -> impl Runnable + Send {
        struct RejectPromise(TrustedPromise, Error);
        impl Runnable for RejectPromise {
            fn main_thread_handler(self: Box<Self>, script_thread: &ScriptThread) {
                debug!("Rejecting promise.");
                let this = *self;
                let cx = script_thread.get_cx();
                let promise = this.0.root();
                let _ac = JSAutoCompartment::new(cx, promise.reflector().get_jsobject().get());
                promise.reject_error(cx, this.1);
            }
        }
        RejectPromise(self, error)
    }

    /// A runnable which will resolve the promise.
    #[allow(unrooted_must_root)]
    pub fn resolve_runnable<T>(self, value: T) -> impl Runnable + Send where
        T: ToJSValConvertible + Send
    {
        struct ResolvePromise<T>(TrustedPromise, T);
        impl<T: ToJSValConvertible> Runnable for ResolvePromise<T> {
            fn main_thread_handler(self: Box<Self>, script_thread: &ScriptThread) {
                debug!("Resolving promise.");
                let this = *self;
                let cx = script_thread.get_cx();
                let promise = this.0.root();
                let _ac = JSAutoCompartment::new(cx, promise.reflector().get_jsobject().get());
                promise.resolve_native(cx, &this.1);
            }
        }
        ResolvePromise(self, value)
    }
}

/// A safe wrapper around a raw pointer to a DOM object that can be
/// shared among threads for use in asynchronous operations. The underlying
/// DOM object is guaranteed to live at least as long as the last outstanding
/// `Trusted<T>` instance.
#[allow_unrooted_interior]
pub struct Trusted<T: DomObject> {
    /// A pointer to the Rust DOM object of type T, but void to allow
    /// sending `Trusted<T>` between threads, regardless of T's sendability.
    refcount: Arc<TrustedReference>,
    owner_thread: *const libc::c_void,
    phantom: PhantomData<T>,
}

unsafe impl<T: DomObject> Send for Trusted<T> {}

impl<T: DomObject> Trusted<T> {
    /// Create a new `Trusted<T>` instance from an existing DOM pointer. The DOM object will
    /// be prevented from being GCed for the duration of the resulting `Trusted<T>` object's
    /// lifetime.
    pub fn new(ptr: &T) -> Trusted<T> {
        LIVE_REFERENCES.with(|ref r| {
            let r = r.borrow();
            let live_references = r.as_ref().unwrap();
            let refcount = live_references.addref(&*ptr as *const T);
            Trusted {
                refcount: refcount,
                owner_thread: (&*live_references) as *const _ as *const libc::c_void,
                phantom: PhantomData,
            }
        })
    }

    /// Obtain a usable DOM pointer from a pinned `Trusted<T>` value. Fails if used on
    /// a different thread than the original value from which this `Trusted<T>` was
    /// obtained.
    pub fn root(&self) -> Root<T> {
        assert!(LIVE_REFERENCES.with(|ref r| {
            let r = r.borrow();
            let live_references = r.as_ref().unwrap();
            self.owner_thread == (&*live_references) as *const _ as *const libc::c_void
        }));
        unsafe {
            Root::new(NonZero::new_unchecked(self.refcount.0 as *const T))
        }
    }
}

impl<T: DomObject> Clone for Trusted<T> {
    fn clone(&self) -> Trusted<T> {
        Trusted {
            refcount: self.refcount.clone(),
            owner_thread: self.owner_thread,
            phantom: PhantomData,
        }
    }
}

/// The set of live, pinned DOM objects that are currently prevented
/// from being garbage collected due to outstanding references.
#[allow(unrooted_must_root)]
pub struct LiveDOMReferences {
    // keyed on pointer to Rust DOM object
    reflectable_table: RefCell<HashMap<*const libc::c_void, Weak<TrustedReference>>>,
    promise_table: RefCell<HashMap<*const Promise, Vec<Rc<Promise>>>>,
}

impl LiveDOMReferences {
    /// Set up the thread-local data required for storing the outstanding DOM references.
    pub fn initialize() {
        LIVE_REFERENCES.with(|ref r| {
            *r.borrow_mut() = Some(LiveDOMReferences {
                reflectable_table: RefCell::new(HashMap::new()),
                promise_table: RefCell::new(HashMap::new()),
            })
        });
    }

    #[allow(unrooted_must_root)]
    fn addref_promise(&self, promise: Rc<Promise>) {
        let mut table = self.promise_table.borrow_mut();
        table.entry(&*promise).or_insert(vec![]).push(promise)
    }

    fn addref<T: DomObject>(&self, ptr: *const T) -> Arc<TrustedReference> {
        let mut table = self.reflectable_table.borrow_mut();
        let capacity = table.capacity();
        let len = table.len();
        if (0 < capacity) && (capacity <= len) {
            info!("growing refcounted references by {}", len);
            remove_nulls(&mut table);
            table.reserve(len);
        }
        match table.entry(ptr as *const libc::c_void) {
            Occupied(mut entry) => match entry.get().upgrade() {
                Some(refcount) => refcount,
                None => {
                    let refcount = Arc::new(TrustedReference::new(ptr));
                    entry.insert(Arc::downgrade(&refcount));
                    refcount
                },
            },
            Vacant(entry) => {
                let refcount = Arc::new(TrustedReference::new(ptr));
                entry.insert(Arc::downgrade(&refcount));
                refcount
            }
        }
    }
}

/// Remove null entries from the live references table
fn remove_nulls<K: Eq + Hash + Clone, V> (table: &mut HashMap<K, Weak<V>>) {
    let to_remove: Vec<K> =
        table.iter()
        .filter(|&(_, value)| Weak::upgrade(value).is_none())
        .map(|(key, _)| key.clone())
        .collect();
    info!("removing {} refcounted references", to_remove.len());
    for key in to_remove {
        table.remove(&key);
    }
}

/// A JSTraceDataOp for tracing reflectors held in LIVE_REFERENCES
#[allow(unrooted_must_root)]
pub unsafe extern "C" fn trace_refcounted_objects(tracer: *mut JSTracer,
                                                  _data: *mut os::raw::c_void) {
    info!("tracing live refcounted references");
    LIVE_REFERENCES.with(|ref r| {
        let r = r.borrow();
        let live_references = r.as_ref().unwrap();
        {
            let mut table = live_references.reflectable_table.borrow_mut();
            remove_nulls(&mut table);
            for obj in table.keys() {
                let reflectable = &*(*obj as *const Reflector);
                trace_reflector(tracer, "refcounted", reflectable);
            }
        }

        {
            let table = live_references.promise_table.borrow_mut();
            for promise in table.keys() {
                trace_reflector(tracer, "refcounted", (**promise).reflector());
            }
        }
    });
}
<commit_msg>Auto merge of #18021 - ferjm:trusted.doc, r=jdm<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A generic, safe mechanism by which DOM objects can be pinned and transferred
//! between threads (or intra-thread for asynchronous events). Akin to Gecko's
//! nsMainThreadPtrHandle, this uses thread-safe reference counting and ensures
//! that the actual SpiderMonkey GC integration occurs on the script thread via
//! weak refcounts. Ownership of a `Trusted<T>` object means the DOM object of
//! type T to which it points remains alive. Any other behaviour is undefined.
//! To guarantee the lifetime of a DOM object when performing asynchronous operations,
//! obtain a `Trusted<T>` from that object and pass it along with each operation.
//! A usable pointer to the original DOM object can be obtained on the script thread
//! from a `Trusted<T>` via the `root` method.
//!
//! The implementation of `Trusted<T>` is as follows:
//! The `Trusted<T>` object contains an atomic reference counted pointer to the Rust DOM object.
//! A hashtable resides in the script thread, keyed on the pointer.
//! The values in this hashtable are weak reference counts. When a `Trusted<T>` object is
//! created or cloned, the reference count is increased. When a `Trusted<T>` is dropped, the count
//! decreases. If the count hits zero, the weak reference is emptied, and is removed from
//! its hash table during the next GC. During GC, the entries of the hash table are counted
//! as JS roots.

use core::nonzero::NonZero;
use dom::bindings::conversions::ToJSValConvertible;
use dom::bindings::error::Error;
use dom::bindings::js::Root;
use dom::bindings::reflector::{DomObject, Reflector};
use dom::bindings::trace::trace_reflector;
use dom::promise::Promise;
use js::jsapi::JSAutoCompartment;
use js::jsapi::JSTracer;
use libc;
use script_thread::Runnable;
use script_thread::ScriptThread;
use std::cell::RefCell;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::hash_map::HashMap;
use std::hash::Hash;
use std::marker::PhantomData;
use std::os;
use std::rc::Rc;
use std::sync::{Arc, Weak};

#[allow(missing_docs)]  // FIXME
mod dummy {  // Attributes don’t apply through the macro.
    use std::cell::RefCell;
    use std::rc::Rc;
    use super::LiveDOMReferences;
    thread_local!(pub static LIVE_REFERENCES: Rc<RefCell<Option<LiveDOMReferences>>> =
            Rc::new(RefCell::new(None)));
}
pub use self::dummy::LIVE_REFERENCES;

/// A pointer to a Rust DOM object that needs to be destroyed.
pub struct TrustedReference(*const libc::c_void);
unsafe impl Send for TrustedReference {}

impl TrustedReference {
    fn new<T: DomObject>(ptr: *const T) -> TrustedReference {
        TrustedReference(ptr as *const libc::c_void)
    }
}

/// A safe wrapper around a DOM Promise object that can be shared among threads for use
/// in asynchronous operations. The underlying DOM object is guaranteed to live at least
/// as long as the last outstanding `TrustedPromise` instance. These values cannot be cloned,
/// only created from existing Rc<Promise> values.
pub struct TrustedPromise {
    dom_object: *const Promise,
    owner_thread: *const libc::c_void,
}

unsafe impl Send for TrustedPromise {}

impl TrustedPromise {
    /// Create a new `TrustedPromise` instance from an existing DOM object. The object will
    /// be prevented from being GCed for the duration of the resulting `TrustedPromise` object's
    /// lifetime.
    #[allow(unrooted_must_root)]
    pub fn new(promise: Rc<Promise>) -> TrustedPromise {
        LIVE_REFERENCES.with(|ref r| {
            let r = r.borrow();
            let live_references = r.as_ref().unwrap();
            let ptr = &*promise as *const Promise;
            live_references.addref_promise(promise);
            TrustedPromise {
                dom_object: ptr,
                owner_thread: (&*live_references) as *const _ as *const libc::c_void,
            }
        })
    }

    /// Obtain a usable DOM Promise from a pinned `TrustedPromise` value. Fails if used on
    /// a different thread than the original value from which this `TrustedPromise` was
    /// obtained.
    #[allow(unrooted_must_root)]
    pub fn root(self) -> Rc<Promise> {
        LIVE_REFERENCES.with(|ref r| {
            let r = r.borrow();
            let live_references = r.as_ref().unwrap();
            assert!(self.owner_thread == (&*live_references) as *const _ as *const libc::c_void);
            // Borrow-check error requires the redundant `let promise = ...; promise` here.
            let promise = match live_references.promise_table.borrow_mut().entry(self.dom_object) {
                Occupied(mut entry) => {
                    let promise = {
                        let promises = entry.get_mut();
                        promises.pop().expect("rooted promise list unexpectedly empty")
                    };
                    if entry.get().is_empty() {
                        entry.remove();
                    }
                    promise
                }
                Vacant(_) => unreachable!(),
            };
            promise
        })
    }

    /// A runnable which will reject the promise.
    #[allow(unrooted_must_root)]
    pub fn reject_runnable(self, error: Error) -> impl Runnable + Send {
        struct RejectPromise(TrustedPromise, Error);
        impl Runnable for RejectPromise {
            fn main_thread_handler(self: Box<Self>, script_thread: &ScriptThread) {
                debug!("Rejecting promise.");
                let this = *self;
                let cx = script_thread.get_cx();
                let promise = this.0.root();
                let _ac = JSAutoCompartment::new(cx, promise.reflector().get_jsobject().get());
                promise.reject_error(cx, this.1);
            }
        }
        RejectPromise(self, error)
    }

    /// A runnable which will resolve the promise.
    #[allow(unrooted_must_root)]
    pub fn resolve_runnable<T>(self, value: T) -> impl Runnable + Send where
        T: ToJSValConvertible + Send
    {
        struct ResolvePromise<T>(TrustedPromise, T);
        impl<T: ToJSValConvertible> Runnable for ResolvePromise<T> {
            fn main_thread_handler(self: Box<Self>, script_thread: &ScriptThread) {
                debug!("Resolving promise.");
                let this = *self;
                let cx = script_thread.get_cx();
                let promise = this.0.root();
                let _ac = JSAutoCompartment::new(cx, promise.reflector().get_jsobject().get());
                promise.resolve_native(cx, &this.1);
            }
        }
        ResolvePromise(self, value)
    }
}

/// A safe wrapper around a raw pointer to a DOM object that can be
/// shared among threads for use in asynchronous operations. The underlying
/// DOM object is guaranteed to live at least as long as the last outstanding
/// `Trusted<T>` instance.
#[allow_unrooted_interior]
pub struct Trusted<T: DomObject> {
    /// A pointer to the Rust DOM object of type T, but void to allow
    /// sending `Trusted<T>` between threads, regardless of T's sendability.
    refcount: Arc<TrustedReference>,
    owner_thread: *const libc::c_void,
    phantom: PhantomData<T>,
}

unsafe impl<T: DomObject> Send for Trusted<T> {}

impl<T: DomObject> Trusted<T> {
    /// Create a new `Trusted<T>` instance from an existing DOM pointer. The DOM object will
    /// be prevented from being GCed for the duration of the resulting `Trusted<T>` object's
    /// lifetime.
    pub fn new(ptr: &T) -> Trusted<T> {
        LIVE_REFERENCES.with(|ref r| {
            let r = r.borrow();
            let live_references = r.as_ref().unwrap();
            let refcount = live_references.addref(&*ptr as *const T);
            Trusted {
                refcount: refcount,
                owner_thread: (&*live_references) as *const _ as *const libc::c_void,
                phantom: PhantomData,
            }
        })
    }

    /// Obtain a usable DOM pointer from a pinned `Trusted<T>` value. Fails if used on
    /// a different thread than the original value from which this `Trusted<T>` was
    /// obtained.
    pub fn root(&self) -> Root<T> {
        assert!(LIVE_REFERENCES.with(|ref r| {
            let r = r.borrow();
            let live_references = r.as_ref().unwrap();
            self.owner_thread == (&*live_references) as *const _ as *const libc::c_void
        }));
        unsafe {
            Root::new(NonZero::new_unchecked(self.refcount.0 as *const T))
        }
    }
}

impl<T: DomObject> Clone for Trusted<T> {
    fn clone(&self) -> Trusted<T> {
        Trusted {
            refcount: self.refcount.clone(),
            owner_thread: self.owner_thread,
            phantom: PhantomData,
        }
    }
}

/// The set of live, pinned DOM objects that are currently prevented
/// from being garbage collected due to outstanding references.
#[allow(unrooted_must_root)]
pub struct LiveDOMReferences {
    // keyed on pointer to Rust DOM object
    reflectable_table: RefCell<HashMap<*const libc::c_void, Weak<TrustedReference>>>,
    promise_table: RefCell<HashMap<*const Promise, Vec<Rc<Promise>>>>,
}

impl LiveDOMReferences {
    /// Set up the thread-local data required for storing the outstanding DOM references.
    pub fn initialize() {
        LIVE_REFERENCES.with(|ref r| {
            *r.borrow_mut() = Some(LiveDOMReferences {
                reflectable_table: RefCell::new(HashMap::new()),
                promise_table: RefCell::new(HashMap::new()),
            })
        });
    }

    #[allow(unrooted_must_root)]
    fn addref_promise(&self, promise: Rc<Promise>) {
        let mut table = self.promise_table.borrow_mut();
        table.entry(&*promise).or_insert(vec![]).push(promise)
    }

    fn addref<T: DomObject>(&self, ptr: *const T) -> Arc<TrustedReference> {
        let mut table = self.reflectable_table.borrow_mut();
        let capacity = table.capacity();
        let len = table.len();
        if (0 < capacity) && (capacity <= len) {
            info!("growing refcounted references by {}", len);
            remove_nulls(&mut table);
            table.reserve(len);
        }
        match table.entry(ptr as *const libc::c_void) {
            Occupied(mut entry) => match entry.get().upgrade() {
                Some(refcount) => refcount,
                None => {
                    let refcount = Arc::new(TrustedReference::new(ptr));
                    entry.insert(Arc::downgrade(&refcount));
                    refcount
                },
            },
            Vacant(entry) => {
                let refcount = Arc::new(TrustedReference::new(ptr));
                entry.insert(Arc::downgrade(&refcount));
                refcount
            }
        }
    }
}

/// Remove null entries from the live references table
fn remove_nulls<K: Eq + Hash + Clone, V> (table: &mut HashMap<K, Weak<V>>) {
    let to_remove: Vec<K> =
        table.iter()
        .filter(|&(_, value)| Weak::upgrade(value).is_none())
        .map(|(key, _)| key.clone())
        .collect();
    info!("removing {} refcounted references", to_remove.len());
    for key in to_remove {
        table.remove(&key);
    }
}

/// A JSTraceDataOp for tracing reflectors held in LIVE_REFERENCES
#[allow(unrooted_must_root)]
pub unsafe extern "C" fn trace_refcounted_objects(tracer: *mut JSTracer,
                                                  _data: *mut os::raw::c_void) {
    info!("tracing live refcounted references");
    LIVE_REFERENCES.with(|ref r| {
        let r = r.borrow();
        let live_references = r.as_ref().unwrap();
        {
            let mut table = live_references.reflectable_table.borrow_mut();
            remove_nulls(&mut table);
            for obj in table.keys() {
                let reflectable = &*(*obj as *const Reflector);
                trace_reflector(tracer, "refcounted", reflectable);
            }
        }

        {
            let table = live_references.promise_table.borrow_mut();
            for promise in table.keys() {
                trace_reflector(tracer, "refcounted", (**promise).reflector());
            }
        }
    });
}
<|endoftext|>


<commit_before>use super::response::Response;
use super::request::Request;
use super::alloy::Alloy;

/// The Status returned by `Ingot's` `enter` and `exit` methods. This indicates
/// to the `Furnace` whether this is a terminal `Ingot` or whether to continue
/// passing the `Request` and `Response` down the `Furnace's` stack.
///
/// Most `Furnaces` will ignore the returned `Status` from the `exit` method of
/// `Ingots`.
pub enum Status {
    /// `Continue` indicates that this is an intermediate `Ingot` in the stack
    /// and the `Furnace` should continue passing requests down the `Furnace's`
    /// stack.
    ///
    /// Most `Ingots` will return `Continue` from both `enter` and `exit`.
    Continue,

    /// `Unwind` indicates that this is a terminal `Ingot` or something went
    /// wrong. It can be used to immediately stop passing requests down the
    /// `Furnace's` stack and start calling `exit` of all previous `Ingots`.
    ///
    /// For instance, an authorization `Ingot` might return `Unwind` if the
    /// request fails an authentication check, and `Continue` otherwise.
    Unwind
}

/// All middleware should implement `Ingot`, which allows it to be `smelted`
/// to a `Furnace` so that it will be called for each incoming request.
///
/// There are two sorts of data associated with `Ingots`, data internal
/// to the `Ingot` and APIs that the `Ingot` would like to expose to `Ingots`
/// further down the stack or terminal controllers.
///
/// Internal data should be stored on the `struct` that implements `Ingot`
/// itself. All `Ingots` are cloned for each client request, so the object
/// initially smelted on to the `Iron` instance will be provided as `&self` to
/// enter for every request. Data stored on `Ingot` instances does _not_ persist
/// between requests and is _not_ shared between different, concurrent, requests.
/// The same is true for data stored on `Alloys`.
///
/// External data should be stored in the `Alloy` passed to both `enter` and
/// `exit`. `Alloy` is a thin wrapper around `AnyMap` and is effectively a
/// a key value store from a type to an instance of that type. This means
/// that each `Ingot` can have a unique type that it stores in the `Alloy`.
/// This can either be an instance of that `Ingot` or some other type. Since
/// the same `Alloy` is passed to all further `Ingots` in the `Furnace`, this
/// scheme allows you to expose data or functionality to future `Ingots`.
pub trait Ingot<Rq: Request, Rs: Response>: Send + Clone {
    fn enter(&mut self, _request: &mut Rq, _response: &mut Rs, _alloy: &mut Alloy) -> Status {
        Continue
    }
    fn exit(&mut self, _request: &mut Rq, _response: &mut Rs, _alloy: &mut Alloy) -> Status {
        Continue
    }
    fn clone_box(&self) -> Box<Ingot<Rq, Rs>> { box self.clone() as Box<Ingot<Rq, Rs>> }
}

impl<Rq: Request, Rs: Response> Clone for Box<Ingot<Rq, Rs>> {
    fn clone(&self) -> Box<Ingot<Rq, Rs>> { self.clone_box() }
}
<commit_msg>(doc) Documented Ingot trait methods.<commit_after>use super::response::Response;
use super::request::Request;
use super::alloy::Alloy;

/// The Status returned by `Ingot's` `enter` and `exit` methods. This indicates
/// to the `Furnace` whether this is a terminal `Ingot` or whether to continue
/// passing the `Request` and `Response` down the `Furnace's` stack.
///
/// Most `Furnaces` will ignore the returned `Status` from the `exit` method of
/// `Ingots`.
pub enum Status {
    /// `Continue` indicates that this is an intermediate `Ingot` in the stack
    /// and the `Furnace` should continue passing requests down the `Furnace's`
    /// stack.
    ///
    /// Most `Ingots` will return `Continue` from both `enter` and `exit`.
    Continue,

    /// `Unwind` indicates that this is a terminal `Ingot` or something went
    /// wrong. It can be used to immediately stop passing requests down the
    /// `Furnace's` stack and start calling `exit` of all previous `Ingots`.
    ///
    /// For instance, an authorization `Ingot` might return `Unwind` if the
    /// request fails an authentication check, and `Continue` otherwise.
    Unwind
}

/// All middleware should implement `Ingot`, which allows it to be `smelted`
/// to a `Furnace` so that it will be called for each incoming request.
///
/// There are two sorts of data associated with `Ingots`, data internal
/// to the `Ingot` and data that the `Ingot` would like to expose to `Ingots`
/// further down the stack or terminal controllers.
///
/// Internal data should be stored on the `struct` that implements `Ingot`
/// itself. All `Ingots` are cloned for each client request, so the object
/// initially smelted on to the `Iron` instance will be provided as `&self` to
/// enter for every request. Data stored on `Ingot` instances does _not_ persist
/// between requests and is _not_ shared between different, concurrent, requests.
/// The same is true for data stored on `Alloys`.
///
/// External data should be stored in the `Alloy` passed to both `enter` and
/// `exit`. `Alloy` is a thin wrapper around `AnyMap` and is effectively a
/// a key value store from a type to an instance of that type. This means
/// that each `Ingot` can have a unique type that it stores in the `Alloy`.
/// This can either be an instance of that `Ingot` or some other type. Since
/// the same `Alloy` is passed to all further `Ingots` in the `Furnace`, this
/// scheme allows you to expose data or functionality to future `Ingots`.
pub trait Ingot<Rq: Request, Rs: Response>: Send + Clone {
    /// `enter` is called for each `Ingot` in a `Furnace` as a client request
    /// comes down the stack. `Ingots` should expose data through `Alloy` and
    /// store any data that will persist through the request here.
    ///
    /// returning `Unwind` from this handler will cause the `Furnace` to stop
    /// going down the `Furnace's` stack and start bubbling back up and calling
    /// `exit`.
    fn enter(&mut self, _request: &mut Rq, _response: &mut Rs, _alloy: &mut Alloy) -> Status {
        Continue
    }

    /// `exit` is called for each `Ingot` in `Furnace` that has had it's `enter`
    /// method called for this request. `Ingot's``exit` method will be called
    /// as the stack is unwound in FILO order. `Ingots` have their `exit`
    /// methods called in opposite order from which `enter` was called, which
    /// is FIFO.
    ///
    /// While this method must return a `Status`, most `Furnaces` will ignore
    /// this method's return value.
    fn exit(&mut self, _request: &mut Rq, _response: &mut Rs, _alloy: &mut Alloy) -> Status {
        Continue
    }

    fn clone_box(&self) -> Box<Ingot<Rq, Rs>> { box self.clone() as Box<Ingot<Rq, Rs>> }
}

impl<Rq: Request, Rs: Response> Clone for Box<Ingot<Rq, Rs>> {
    fn clone(&self) -> Box<Ingot<Rq, Rs>> { self.clone_box() }
}
<|endoftext|>


<commit_before>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

//! Provides a "cursor" over a mutable byte buffer.
//!
//! [`Cursor`] provides a `consume()` function, which can be called repeatedly
//! to take portions of the buffer. An internal cursor will track the location
//! of the buffer. This method is used to implement [`Write`] for [`Cursor`].
//!
//! This type is useful when you want to feed a scratch buffer into a function
//! that performs I/O operations on a buffer, and then extract how much of the
//! buffer was read or written. This is especialy useful when used in
//! conjunction with [`ToWire`]:
//! ```
//! # use manticore::io::*;
//! # use manticore::protocol::wire::*;
//! # struct MyMessage;
//! # impl ToWire for MyMessage {
//! #     fn to_wire<W: Write>(&self, mut w: W) -> Result<(), ToWireError> {
//! #         w.write_bytes(&[1, 2, 3, 4]);
//! #         Ok(())
//! #     }
//! # }
//! let msg = MyMessage;
//! let mut buf = [0; 256];
//!
//! let mut cursor = Cursor::new(&mut buf);
//! msg.to_wire(&mut cursor);
//!
//! let msg_bytes = cursor.take_consumed_bytes();
//! assert_ne!(msg_bytes.len(), 0);
//! ```
//!
//! [`Cursor`]: struct.Cursor.html
//! [`Write`]: ../trait.Write.html
//! [`ToWire`]: ../../protocol/wire/trait.ToWire.html

use core::mem;

use crate::io;
use crate::io::Write;

/// A position for using with [`Cursor::seek()`].
///
/// [`Cursor::seek()`]: struct.Cursor.html#method.seek
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum SeekPos {
    /// Seek absolutely, from the start of the buffer.
    Abs(usize),
    /// Seek relatively, from the current cursor value.
    Rel(isize),
}

/// A cursor over a buffer of memory.
///
/// See the [module documentation](index.html) for more information.
pub struct Cursor<'a> {
    buf: &'a mut [u8],
    // Invariant: cursor <= buf.len().
    cursor: usize,
}

impl<'a> Cursor<'a> {
    /// Creates a new `Cursor` for the given buffer.
    pub fn new(buf: &'a mut [u8]) -> Self {
        Self { buf, cursor: 0 }
    }

    /// Consumes `n` bytes from the underlying buffer.
    ///
    /// If `n` bytes are unavailable, `BufferExhausted` is returned.
    pub fn consume(&mut self, n: usize) -> Result<&mut [u8], io::Error> {
        let end = self
            .cursor
            .checked_add(n)
            .ok_or(io::Error::BufferExhausted)?;
        if self.buf.len() < end {
            return Err(io::Error::BufferExhausted);
        }
        let output = &mut self.buf[self.cursor..end];
        self.cursor = end;

        Ok(output)
    }

    /// Seek to an offset within the underlying buffer.
    ///
    /// This function effectively sets the underlying cursor used to partition
    /// the buffer into "consumed" and "unconsumed portions. This function can
    /// be used to temporarially backtrack in combination with
    /// `consumed_len()`.
    ///
    /// Returns [`Error::BufferExhausted`] when attempting to seek beyond the end
    /// of the buffer.
    ///
    /// [`Error::BufferExhausted`]: enum.Error.html#variant.BufferExhausted
    ///
    /// # Example
    /// ```
    /// # use manticore::io::*;
    /// # use manticore::io::cursor::*;
    /// # let mut buf = [0; 16];
    /// let mut cursor = Cursor::new(&mut buf);
    /// cursor.write_bytes(b"barbar")?;
    ///
    /// let mark = cursor.consumed_len();
    /// cursor.seek(SeekPos::Rel(-5))?;
    /// cursor.write_bytes(b"foo")?;
    /// cursor.seek(SeekPos::Abs(mark))?;
    /// assert_eq!(cursor.consumed_bytes(), b"bfooar");
    ///
    /// # Ok::<(), Error>(())
    /// ```
    pub fn seek(&mut self, pos: SeekPos) -> Result<(), io::Error> {
        let offset = match pos {
            SeekPos::Abs(offset) if offset <= self.buf.len() => offset,
            SeekPos::Rel(offset) => {
                let offset = (self.consumed_len() as isize)
                    .checked_add(offset)
                    .ok_or(io::Error::BufferExhausted)?;
                if offset < 0 {
                    return Err(io::Error::BufferExhausted);
                }
                offset as usize
            }
            _ => return Err(io::Error::BufferExhausted),
        };
        self.cursor = offset;
        Ok(())
    }

    /// Returns the number of bytes consumed thus far.
    pub fn consumed_len(&self) -> usize {
        self.cursor
    }

    /// Returns the portion of the buffer which has been consumed thus far.
    pub fn consumed_bytes(&self) -> &[u8] {
        &self.buf[..self.cursor]
    }

    /// Takes the portion of the buffer which has been consumed so far,
    /// resetting the cursor value back to zero.
    ///
    /// This function leaves `self` as if it had been newly initialized with
    /// the unconsumed portion of the buffer. Repeatedly calling this function
    /// with no other intervening operations will return `&mut []`.
    ///
    /// Because this function returns a `'a` reference, it is not bound to the
    /// `Cursor` that originally contained it. This function is useful when
    /// a desired reference needs to have the lifetime of the buffer that went
    /// into the `Cursor`, rather than the `Cursor`'s own local lifetime.
    pub fn take_consumed_bytes(&mut self) -> &'a mut [u8] {
        let (output, rest) =
            mem::replace(&mut self.buf, &mut []).split_at_mut(self.cursor);
        self.cursor = 0;
        self.buf = rest;
        output
    }
}

impl Write for Cursor<'_> {
    fn write_bytes(&mut self, buf: &[u8]) -> Result<(), io::Error> {
        let dest = self.consume(buf.len())?;
        dest.copy_from_slice(buf);
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn cursor() {
        let mut buf = [0; 8];
        let mut cursor = Cursor::new(&mut buf);

        cursor.write_le::<u32>(0xffaaffaa).unwrap();
        assert_eq!(cursor.consumed_len(), 4);
        assert_eq!(cursor.consumed_bytes(), &[0xaa, 0xff, 0xaa, 0xff]);
        let bytes = cursor.take_consumed_bytes();
        assert_eq!(bytes, &[0xaa, 0xff, 0xaa, 0xff]);
        assert_eq!(cursor.consumed_len(), 0);

        assert!(cursor.write_bytes(&[0x55; 7]).is_err());
    }
}
<commit_msg>[io] Add io::Cursor::consume_with_prior()<commit_after>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

//! Provides a "cursor" over a mutable byte buffer.
//!
//! [`Cursor`] provides a `consume()` function, which can be called repeatedly
//! to take portions of the buffer. An internal cursor will track the location
//! of the buffer. This method is used to implement [`Write`] for [`Cursor`].
//!
//! This type is useful when you want to feed a scratch buffer into a function
//! that performs I/O operations on a buffer, and then extract how much of the
//! buffer was read or written. This is especialy useful when used in
//! conjunction with [`ToWire`]:
//! ```
//! # use manticore::io::*;
//! # use manticore::protocol::wire::*;
//! # struct MyMessage;
//! # impl ToWire for MyMessage {
//! #     fn to_wire<W: Write>(&self, mut w: W) -> Result<(), ToWireError> {
//! #         w.write_bytes(&[1, 2, 3, 4]);
//! #         Ok(())
//! #     }
//! # }
//! let msg = MyMessage;
//! let mut buf = [0; 256];
//!
//! let mut cursor = Cursor::new(&mut buf);
//! msg.to_wire(&mut cursor);
//!
//! let msg_bytes = cursor.take_consumed_bytes();
//! assert_ne!(msg_bytes.len(), 0);
//! ```
//!
//! [`Cursor`]: struct.Cursor.html
//! [`Write`]: ../trait.Write.html
//! [`ToWire`]: ../../protocol/wire/trait.ToWire.html

use core::mem;

use crate::io;
use crate::io::Write;

/// A position for using with [`Cursor::seek()`].
///
/// [`Cursor::seek()`]: struct.Cursor.html#method.seek
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum SeekPos {
    /// Seek absolutely, from the start of the buffer.
    Abs(usize),
    /// Seek relatively, from the current cursor value.
    Rel(isize),
}

/// A cursor over a buffer of memory.
///
/// See the [module documentation](index.html) for more information.
pub struct Cursor<'a> {
    buf: &'a mut [u8],
    // Invariant: cursor <= buf.len().
    cursor: usize,
}

impl<'a> Cursor<'a> {
    /// Creates a new `Cursor` for the given buffer.
    pub fn new(buf: &'a mut [u8]) -> Self {
        Self { buf, cursor: 0 }
    }

    /// Consumes `n` bytes from the underlying buffer.
    ///
    /// If `n` bytes are unavailable, `BufferExhausted` is returned.
    pub fn consume(&mut self, n: usize) -> Result<&mut [u8], io::Error> {
        self.consume_with_prior(n).map(|(_, bytes)| bytes)
    }

    /// Consumes `n` bytes from the underlying buffer, returning the prior
    /// consumed portion as well.
    ///
    /// This function is useful for when it is necessary to incorporate the
    /// contents of a prior-consumed buffer into the newly consumed buffer.
    ///
    /// If `n` bytes are unavailable, `None` is returned.
    pub fn consume_with_prior(
        &mut self,
        n: usize,
    ) -> Result<(&mut [u8], &mut [u8]), io::Error> {
        let end = self
            .cursor
            .checked_add(n)
            .ok_or(io::Error::BufferExhausted)?;
        if self.buf.len() < end {
            return Err(io::Error::BufferExhausted);
        }
        let output = self.buf[..end].split_at_mut(self.cursor);
        self.cursor = end;

        Ok(output)
    }

    /// Seek to an offset within the underlying buffer.
    ///
    /// This function effectively sets the underlying cursor used to partition
    /// the buffer into "consumed" and "unconsumed portions. This function can
    /// be used to temporarially backtrack in combination with
    /// `consumed_len()`.
    ///
    /// Returns [`Error::BufferExhausted`] when attempting to seek beyond the end
    /// of the buffer.
    ///
    /// [`Error::BufferExhausted`]: enum.Error.html#variant.BufferExhausted
    ///
    /// # Example
    /// ```
    /// # use manticore::io::*;
    /// # use manticore::io::cursor::*;
    /// # let mut buf = [0; 16];
    /// let mut cursor = Cursor::new(&mut buf);
    /// cursor.write_bytes(b"barbar")?;
    ///
    /// let mark = cursor.consumed_len();
    /// cursor.seek(SeekPos::Rel(-5))?;
    /// cursor.write_bytes(b"foo")?;
    /// cursor.seek(SeekPos::Abs(mark))?;
    /// assert_eq!(cursor.consumed_bytes(), b"bfooar");
    ///
    /// # Ok::<(), Error>(())
    /// ```
    pub fn seek(&mut self, pos: SeekPos) -> Result<(), io::Error> {
        let offset = match pos {
            SeekPos::Abs(offset) if offset <= self.buf.len() => offset,
            SeekPos::Rel(offset) => {
                let offset = (self.consumed_len() as isize)
                    .checked_add(offset)
                    .ok_or(io::Error::BufferExhausted)?;
                if offset < 0 {
                    return Err(io::Error::BufferExhausted);
                }
                offset as usize
            }
            _ => return Err(io::Error::BufferExhausted),
        };
        self.cursor = offset;
        Ok(())
    }

    /// Returns the number of bytes consumed thus far.
    pub fn consumed_len(&self) -> usize {
        self.cursor
    }

    /// Returns the portion of the buffer which has been consumed thus far.
    pub fn consumed_bytes(&self) -> &[u8] {
        &self.buf[..self.cursor]
    }

    /// Takes the portion of the buffer which has been consumed so far,
    /// resetting the cursor value back to zero.
    ///
    /// This function leaves `self` as if it had been newly initialized with
    /// the unconsumed portion of the buffer. Repeatedly calling this function
    /// with no other intervening operations will return `&mut []`.
    ///
    /// Because this function returns a `'a` reference, it is not bound to the
    /// `Cursor` that originally contained it. This function is useful when
    /// a desired reference needs to have the lifetime of the buffer that went
    /// into the `Cursor`, rather than the `Cursor`'s own local lifetime.
    pub fn take_consumed_bytes(&mut self) -> &'a mut [u8] {
        let (output, rest) =
            mem::replace(&mut self.buf, &mut []).split_at_mut(self.cursor);
        self.cursor = 0;
        self.buf = rest;
        output
    }
}

impl Write for Cursor<'_> {
    fn write_bytes(&mut self, buf: &[u8]) -> Result<(), io::Error> {
        let dest = self.consume(buf.len())?;
        dest.copy_from_slice(buf);
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn cursor() {
        let mut buf = [0; 8];
        let mut cursor = Cursor::new(&mut buf);

        cursor.write_le::<u32>(0xffaaffaa).unwrap();
        assert_eq!(cursor.consumed_len(), 4);
        assert_eq!(cursor.consumed_bytes(), &[0xaa, 0xff, 0xaa, 0xff]);
        let bytes = cursor.take_consumed_bytes();
        assert_eq!(bytes, &[0xaa, 0xff, 0xaa, 0xff]);
        assert_eq!(cursor.consumed_len(), 0);

        assert!(cursor.write_bytes(&[0x55; 7]).is_err());
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use crate::Location;
use std::fmt::{Debug, Display, Write};

pub type DiagnosticsResult<T> = Result<T, Vec<Diagnostic>>;

pub fn diagnostics_result<T>(result: T, diagnostics: Vec<Diagnostic>) -> DiagnosticsResult<T> {
    if diagnostics.is_empty() {
        Ok(result)
    } else {
        Err(diagnostics)
    }
}

/// A diagnostic message as a result of validating some code. This struct is
/// modeled after the LSP Diagnostic type:
/// https://microsoft.github.io/language-server-protocol/specification#diagnostic
///
/// Changes from LSP:
/// - `location` is different from LSP in that it's a file + span instead of
///   just a span.
/// - Unused fields are omitted.
#[derive(Debug)]
pub struct Diagnostic(Box<DiagnosticData>);

impl Diagnostic {
    /// Creates a new error Diagnostic.
    /// Additional locations can be added with the `.annotate()` function.
    pub fn error<T: 'static + DiagnosticDisplay>(message: T, location: Location) -> Self {
        Self(Box::new(DiagnosticData {
            message: Box::new(message),
            location,
            related_information: Vec::new(),
        }))
    }

    /// Annotates this error with an additional location and associated message.
    pub fn annotate<T: 'static + DiagnosticDisplay>(
        mut self,
        message: T,
        location: Location,
    ) -> Self {
        self.0
            .related_information
            .push(DiagnosticRelatedInformation {
                message: Box::new(message),
                location,
            });
        self
    }

    pub fn message(&self) -> &impl DiagnosticDisplay {
        &self.0.message
    }

    pub fn location(&self) -> Location {
        self.0.location
    }

    pub fn related_information(&self) -> &[DiagnosticRelatedInformation] {
        &self.0.related_information
    }

    pub fn print_without_source(&self) -> String {
        let mut result = String::new();
        writeln!(
            result,
            "{message}:{location:?}",
            message = &self.0.message,
            location = self.0.location
        )
        .unwrap();
        if !self.0.related_information.is_empty() {
            for (ix, related) in self.0.related_information.iter().enumerate() {
                writeln!(
                    result,
                    "[related {ix}] {message}:{location:?}",
                    ix = ix + 1,
                    message = related.message,
                    location = related.location
                )
                .unwrap();
            }
        };
        result
    }
}

// statically verify that the Diagnostic type is thread safe
fn _assert_diagnostic_constraints()
where
    Diagnostic: Send + Sync,
{
}

#[derive(Debug)]
struct DiagnosticData {
    /// Human readable error message.
    message: Box<dyn DiagnosticDisplay>,

    /// The primary location of this diagnostic.
    location: Location,

    /// Related diagnostic information, such as other definitions in the case of
    /// a duplicate definition error.
    related_information: Vec<DiagnosticRelatedInformation>,
}

/// Secondary locations attached to a diagnostic.
#[derive(Debug)]
pub struct DiagnosticRelatedInformation {
    /// The message of this related diagnostic information.
    pub message: Box<dyn DiagnosticDisplay>,

    /// The location of this related diagnostic information.
    pub location: Location,
}

/// Trait for diagnostic messages to allow structs that capture
/// some data and can lazily convert it to a message.
pub trait DiagnosticDisplay: Debug + Display + Send + Sync {}

/// Automatically implement the trait if constraints are met, so that
/// implementors don't need to.
impl<T> DiagnosticDisplay for T where T: Debug + Display + Send + Sync {}

impl From<Diagnostic> for Vec<Diagnostic> {
    fn from(diagnostic: Diagnostic) -> Self {
        vec![diagnostic]
    }
}
<commit_msg>Have Diagnostic implement std::error::Error<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use crate::Location;
use std::error::Error;
use std::fmt;
use std::fmt::Write;

pub type DiagnosticsResult<T> = Result<T, Vec<Diagnostic>>;

pub fn diagnostics_result<T>(result: T, diagnostics: Vec<Diagnostic>) -> DiagnosticsResult<T> {
    if diagnostics.is_empty() {
        Ok(result)
    } else {
        Err(diagnostics)
    }
}

/// A diagnostic message as a result of validating some code. This struct is
/// modeled after the LSP Diagnostic type:
/// https://microsoft.github.io/language-server-protocol/specification#diagnostic
///
/// Changes from LSP:
/// - `location` is different from LSP in that it's a file + span instead of
///   just a span.
/// - Unused fields are omitted.
#[derive(fmt::Debug)]
pub struct Diagnostic(Box<DiagnosticData>);

impl Diagnostic {
    /// Creates a new error Diagnostic.
    /// Additional locations can be added with the `.annotate()` function.
    pub fn error<T: 'static + DiagnosticDisplay>(message: T, location: Location) -> Self {
        Self(Box::new(DiagnosticData {
            message: Box::new(message),
            location,
            related_information: Vec::new(),
        }))
    }

    /// Annotates this error with an additional location and associated message.
    pub fn annotate<T: 'static + DiagnosticDisplay>(
        mut self,
        message: T,
        location: Location,
    ) -> Self {
        self.0
            .related_information
            .push(DiagnosticRelatedInformation {
                message: Box::new(message),
                location,
            });
        self
    }

    pub fn message(&self) -> &impl DiagnosticDisplay {
        &self.0.message
    }

    pub fn location(&self) -> Location {
        self.0.location
    }

    pub fn related_information(&self) -> &[DiagnosticRelatedInformation] {
        &self.0.related_information
    }

    pub fn print_without_source(&self) -> String {
        let mut result = String::new();
        writeln!(
            result,
            "{message}:{location:?}",
            message = &self.0.message,
            location = self.0.location
        )
        .unwrap();
        if !self.0.related_information.is_empty() {
            for (ix, related) in self.0.related_information.iter().enumerate() {
                writeln!(
                    result,
                    "[related {ix}] {message}:{location:?}",
                    ix = ix + 1,
                    message = related.message,
                    location = related.location
                )
                .unwrap();
            }
        };
        result
    }
}

impl fmt::Display for Diagnostic {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.print_without_source())
    }
}

impl Error for Diagnostic {}

// statically verify that the Diagnostic type is thread safe
fn _assert_diagnostic_constraints()
where
    Diagnostic: Send + Sync,
{
}

#[derive(fmt::Debug)]
struct DiagnosticData {
    /// Human readable error message.
    message: Box<dyn DiagnosticDisplay>,

    /// The primary location of this diagnostic.
    location: Location,

    /// Related diagnostic information, such as other definitions in the case of
    /// a duplicate definition error.
    related_information: Vec<DiagnosticRelatedInformation>,
}

/// Secondary locations attached to a diagnostic.
#[derive(fmt::Debug)]
pub struct DiagnosticRelatedInformation {
    /// The message of this related diagnostic information.
    pub message: Box<dyn DiagnosticDisplay>,

    /// The location of this related diagnostic information.
    pub location: Location,
}

/// Trait for diagnostic messages to allow structs that capture
/// some data and can lazily convert it to a message.
pub trait DiagnosticDisplay: fmt::Debug + fmt::Display + Send + Sync {}

/// Automatically implement the trait if constraints are met, so that
/// implementors don't need to.
impl<T> DiagnosticDisplay for T where T: fmt::Debug + fmt::Display + Send + Sync {}

impl From<Diagnostic> for Vec<Diagnostic> {
    fn from(diagnostic: Diagnostic) -> Self {
        vec![diagnostic]
    }
}
<|endoftext|>


<commit_before>use std::error;
use std::fmt::{self, Display, Formatter};
use std::io::{self, ErrorKind};

use rmp::decode::{MarkerReadError, ValueReadError};

pub mod value;
pub mod value_ref;

pub use self::value::read_value;
pub use self::value_ref::read_value_ref;

/// This type represents all possible errors that can occur when deserializing a value.
#[derive(Debug)]
pub enum Error {
    /// Error while reading marker byte.
    InvalidMarkerRead(io::Error),
    /// Error while reading data.
    InvalidDataRead(io::Error),
}

impl Error {
    pub fn kind(&self) -> ErrorKind {
        match *self {
            Error::InvalidMarkerRead(ref err) => err.kind(),
            Error::InvalidDataRead(ref err) => err.kind(),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::InvalidMarkerRead(..) => "I/O error while reading marker byte",
            Error::InvalidDataRead(..) => "I/O error while reading non-marker bytes",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::InvalidMarkerRead(ref err) => Some(err),
            Error::InvalidDataRead(ref err) => Some(err),
        }
    }
}

impl Display for Error {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        match *self {
            Error::InvalidMarkerRead(ref err) => {
                write!(fmt, "I/O error while reading marker byte: {}", err)
            }
            Error::InvalidDataRead(ref err) => {
                write!(fmt, "I/O error while reading non-marker bytes: {}", err)
            }
        }
    }
}

impl From<MarkerReadError> for Error {
    fn from(err: MarkerReadError) -> Error {
        Error::InvalidMarkerRead(err.0)
    }
}

impl From<ValueReadError> for Error {
    fn from(err: ValueReadError) -> Error {
        match err {
            ValueReadError::InvalidMarkerRead(err) => Error::InvalidMarkerRead(err),
            ValueReadError::InvalidDataRead(err) => Error::InvalidDataRead(err),
            ValueReadError::TypeMismatch(..) => {
                Error::InvalidMarkerRead(io::Error::new(ErrorKind::Other, "type mismatch"))
            }
        }
    }
}
<commit_msg>feat: add additional error conversion<commit_after>use std::error;
use std::fmt::{self, Display, Formatter};
use std::io::{self, ErrorKind};

use rmp::decode::{MarkerReadError, ValueReadError};

pub mod value;
pub mod value_ref;

pub use self::value::read_value;
pub use self::value_ref::read_value_ref;

/// This type represents all possible errors that can occur when deserializing a value.
#[derive(Debug)]
pub enum Error {
    /// Error while reading marker byte.
    InvalidMarkerRead(io::Error),
    /// Error while reading data.
    InvalidDataRead(io::Error),
}

impl Error {
    pub fn kind(&self) -> ErrorKind {
        match *self {
            Error::InvalidMarkerRead(ref err) => err.kind(),
            Error::InvalidDataRead(ref err) => err.kind(),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::InvalidMarkerRead(..) => "I/O error while reading marker byte",
            Error::InvalidDataRead(..) => "I/O error while reading non-marker bytes",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::InvalidMarkerRead(ref err) => Some(err),
            Error::InvalidDataRead(ref err) => Some(err),
        }
    }
}

impl Display for Error {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        match *self {
            Error::InvalidMarkerRead(ref err) => {
                write!(fmt, "I/O error while reading marker byte: {}", err)
            }
            Error::InvalidDataRead(ref err) => {
                write!(fmt, "I/O error while reading non-marker bytes: {}", err)
            }
        }
    }
}

impl From<MarkerReadError> for Error {
    fn from(err: MarkerReadError) -> Error {
        Error::InvalidMarkerRead(err.0)
    }
}

impl From<ValueReadError> for Error {
    fn from(err: ValueReadError) -> Error {
        match err {
            ValueReadError::InvalidMarkerRead(err) => Error::InvalidMarkerRead(err),
            ValueReadError::InvalidDataRead(err) => Error::InvalidDataRead(err),
            ValueReadError::TypeMismatch(..) => {
                Error::InvalidMarkerRead(io::Error::new(ErrorKind::Other, "type mismatch"))
            }
        }
    }
}

impl From<Error> for io::Error {
    fn from(err: Error) -> io::Error {
        match err {
            Error::InvalidMarkerRead(err) |
            Error::InvalidDataRead(err) => err,
        }
    }
}
<|endoftext|>