<commit_before>// Copyright 2017-2019 int08h LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//!
//! A multi-step (init-update-finish) interface for Ed25519 signing and verification
//!

use ring::rand;
use ring::rand::SecureRandom;
use ring::signature;
use ring::signature::Ed25519KeyPair;

use untrusted::Input;

use std::fmt;
use std::fmt::Formatter;

const INITIAL_BUF_SIZE: usize = 1024;

/// A multi-step (init-update-finish) interface for verifying an Ed25519 signature
#[derive(Debug)]
pub struct Verifier<'a> {
    pubkey: Input<'a>,
    buf: Vec<u8>,
}

impl<'a> Verifier<'a> {
    pub fn new(pubkey: &'a [u8]) -> Self {
        Verifier {
            pubkey: Input::from(pubkey),
            buf: Vec::with_capacity(INITIAL_BUF_SIZE),
        }
    }

    pub fn update(&mut self, data: &[u8]) {
        self.buf.reserve(data.len());
        self.buf.extend_from_slice(data);
    }

    pub fn verify(&self, expected_sig: &[u8]) -> bool {
        let msg = Input::from(&self.buf);
        let sig = Input::from(expected_sig);

        match signature::verify(&signature::ED25519, self.pubkey, msg, sig) {
            Ok(_) => true,
            _ => false,
        }
    }
}

/// A multi-step (init-update-finish) interface for creating an Ed25519 signature
pub struct Signer {
    key_pair: Ed25519KeyPair,
    buf: Vec<u8>,
}

impl Signer {
    pub fn new() -> Self {
        let rng = rand::SystemRandom::new();
        let mut seed = [0u8; 32];
        rng.fill(&mut seed).unwrap();

        Signer::from_seed(&seed)
    }

    pub fn from_seed(seed: &[u8]) -> Self {
        let seed_input = Input::from(seed);
        Signer {
            key_pair: Ed25519KeyPair::from_seed_unchecked(seed_input).unwrap(),
            buf: Vec::with_capacity(INITIAL_BUF_SIZE),
        }
    }

    pub fn update(&mut self, data: &[u8]) {
        self.buf.reserve(data.len());
        self.buf.extend_from_slice(data);
    }

    pub fn sign(&mut self) -> Vec<u8> {
        let signature = self.key_pair.sign(&self.buf).as_ref().to_vec();
        self.buf.clear();

        signature
    }

    pub fn public_key_bytes(&self) -> &[u8] {
        self.key_pair.public_key_bytes()
    }
}

impl fmt::Display for Signer {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", hex::encode(self.public_key_bytes()))
    }
}

impl fmt::Debug for Signer {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(
            f,
            "Signer({}, {:?})",
            hex::encode(self.public_key_bytes()),
            self.buf
        )
    }
}

#[cfg_attr(rustfmt, rustfmt_skip)] // rustfmt errors on the long signature strings
#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn verify_ed25519_sig_on_empty_message() {
        let pubkey = hex::decode(
            "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a",
        ).unwrap();

        let signature = hex::decode(
            "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"
        ).unwrap();

        let v = Verifier::new(&pubkey);
        let result = v.verify(&signature);
        assert_eq!(result, true);
    }

    #[test]
    fn verify_ed25519_sig() {
        let pubkey = hex::decode(
            "c0dac102c4533186e25dc43128472353eaabdb878b152aeb8e001f92d90233a7",
        ).unwrap();

        let message = hex::decode("5f4c8989").unwrap();

        let signature = hex::decode(
            "124f6fc6b0d100842769e71bd530664d888df8507df6c56dedfdb509aeb93416e26b918d38aa06305df3095697c18b2aa832eaa52edc0ae49fbae5a85e150c07"
        ).unwrap();

        let mut v = Verifier::new(&pubkey);
        v.update(&message);
        let result = v.verify(&signature);
        assert_eq!(result, true);
    }

    #[test]
    fn sign_ed25519_empty_message() {
        let seed = hex::decode("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")
            .unwrap();

        let expected_sig = hex::decode(
            "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"
        ).unwrap();

        let mut s = Signer::from_seed(&seed);
        let sig = s.sign();
        assert_eq!(sig, expected_sig);
    }

    #[test]
    fn sign_ed25519_message() {
        let seed = hex::decode("0d4a05b07352a5436e180356da0ae6efa0345ff7fb1572575772e8005ed978e9")
            .unwrap();

        let message = hex::decode("cbc77b").unwrap();

        let expected_sig = hex::decode(
            "d9868d52c2bebce5f3fa5a79891970f309cb6591e3e1702a70276fa97c24b3a8e58606c38c9758529da50ee31b8219cba45271c689afa60b0ea26c99db19b00c"
        ).unwrap();

        let mut s = Signer::from_seed(&seed);
        s.update(&message);
        let sig = s.sign();
        assert_eq!(sig, expected_sig);
    }

    #[test]
    fn sign_verify_round_trip() {
        let seed = hex::decode("334a05b07352a5436e180356da0ae6efa0345ff7fb1572575772e8005ed978e9")
            .unwrap();

        let message = "Hello world".as_bytes();

        let mut signer = Signer::from_seed(&seed);
        signer.update(&message);
        let signature = signer.sign();

        let mut v = Verifier::new(signer.public_key_bytes());
        v.update(&message);
        let result = v.verify(&signature);

        assert_eq!(result, true);
    }
}
<commit_msg>Modernize rustfmt skip attribute<commit_after>// Copyright 2017-2019 int08h LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//!
//! A multi-step (init-update-finish) interface for Ed25519 signing and verification
//!

use ring::rand;
use ring::rand::SecureRandom;
use ring::signature;
use ring::signature::Ed25519KeyPair;

use untrusted::Input;

use std::fmt;
use std::fmt::Formatter;

const INITIAL_BUF_SIZE: usize = 1024;

/// A multi-step (init-update-finish) interface for verifying an Ed25519 signature
#[derive(Debug)]
pub struct Verifier<'a> {
    pubkey: Input<'a>,
    buf: Vec<u8>,
}

impl<'a> Verifier<'a> {
    pub fn new(pubkey: &'a [u8]) -> Self {
        Verifier {
            pubkey: Input::from(pubkey),
            buf: Vec::with_capacity(INITIAL_BUF_SIZE),
        }
    }

    pub fn update(&mut self, data: &[u8]) {
        self.buf.reserve(data.len());
        self.buf.extend_from_slice(data);
    }

    pub fn verify(&self, expected_sig: &[u8]) -> bool {
        let msg = Input::from(&self.buf);
        let sig = Input::from(expected_sig);

        match signature::verify(&signature::ED25519, self.pubkey, msg, sig) {
            Ok(_) => true,
            _ => false,
        }
    }
}

/// A multi-step (init-update-finish) interface for creating an Ed25519 signature
pub struct Signer {
    key_pair: Ed25519KeyPair,
    buf: Vec<u8>,
}

impl Signer {
    pub fn new() -> Self {
        let rng = rand::SystemRandom::new();
        let mut seed = [0u8; 32];
        rng.fill(&mut seed).unwrap();

        Signer::from_seed(&seed)
    }

    pub fn from_seed(seed: &[u8]) -> Self {
        let seed_input = Input::from(seed);
        Signer {
            key_pair: Ed25519KeyPair::from_seed_unchecked(seed_input).unwrap(),
            buf: Vec::with_capacity(INITIAL_BUF_SIZE),
        }
    }

    pub fn update(&mut self, data: &[u8]) {
        self.buf.reserve(data.len());
        self.buf.extend_from_slice(data);
    }

    pub fn sign(&mut self) -> Vec<u8> {
        let signature = self.key_pair.sign(&self.buf).as_ref().to_vec();
        self.buf.clear();

        signature
    }

    pub fn public_key_bytes(&self) -> &[u8] {
        self.key_pair.public_key_bytes()
    }
}

impl fmt::Display for Signer {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", hex::encode(self.public_key_bytes()))
    }
}

impl fmt::Debug for Signer {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(
            f,
            "Signer({}, {:?})",
            hex::encode(self.public_key_bytes()),
            self.buf
        )
    }
}

#[rustfmt::skip] // rustfmt errors on the long signature strings
#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn verify_ed25519_sig_on_empty_message() {
        let pubkey = hex::decode(
            "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a",
        ).unwrap();

        let signature = hex::decode(
            "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"
        ).unwrap();

        let v = Verifier::new(&pubkey);
        let result = v.verify(&signature);
        assert_eq!(result, true);
    }

    #[test]
    fn verify_ed25519_sig() {
        let pubkey = hex::decode(
            "c0dac102c4533186e25dc43128472353eaabdb878b152aeb8e001f92d90233a7",
        ).unwrap();

        let message = hex::decode("5f4c8989").unwrap();

        let signature = hex::decode(
            "124f6fc6b0d100842769e71bd530664d888df8507df6c56dedfdb509aeb93416e26b918d38aa06305df3095697c18b2aa832eaa52edc0ae49fbae5a85e150c07"
        ).unwrap();

        let mut v = Verifier::new(&pubkey);
        v.update(&message);
        let result = v.verify(&signature);
        assert_eq!(result, true);
    }

    #[test]
    fn sign_ed25519_empty_message() {
        let seed = hex::decode("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")
            .unwrap();

        let expected_sig = hex::decode(
            "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"
        ).unwrap();

        let mut s = Signer::from_seed(&seed);
        let sig = s.sign();
        assert_eq!(sig, expected_sig);
    }

    #[test]
    fn sign_ed25519_message() {
        let seed = hex::decode("0d4a05b07352a5436e180356da0ae6efa0345ff7fb1572575772e8005ed978e9")
            .unwrap();

        let message = hex::decode("cbc77b").unwrap();

        let expected_sig = hex::decode(
            "d9868d52c2bebce5f3fa5a79891970f309cb6591e3e1702a70276fa97c24b3a8e58606c38c9758529da50ee31b8219cba45271c689afa60b0ea26c99db19b00c"
        ).unwrap();

        let mut s = Signer::from_seed(&seed);
        s.update(&message);
        let sig = s.sign();
        assert_eq!(sig, expected_sig);
    }

    #[test]
    fn sign_verify_round_trip() {
        let seed = hex::decode("334a05b07352a5436e180356da0ae6efa0345ff7fb1572575772e8005ed978e9")
            .unwrap();

        let message = "Hello world".as_bytes();

        let mut signer = Signer::from_seed(&seed);
        signer.update(&message);
        let signature = signer.sign();

        let mut v = Verifier::new(signer.public_key_bytes());
        v.update(&message);
        let result = v.verify(&signature);

        assert_eq!(result, true);
    }
}
<|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 https://mozilla.org/MPL/2.0/. */

//! Infrastructure to initiate network requests for images needed by the layout
//! thread. The script thread needs to be responsible for them because there's
//! no guarantee that the responsible nodes will still exist in the future if the
//! layout thread holds on to them during asynchronous operations.

use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::root::DomRoot;
use crate::dom::document::Document;
use crate::dom::globalscope::GlobalScope;
use crate::dom::node::{document_from_node, Node};
use crate::dom::performanceresourcetiming::InitiatorType;
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use net_traits::image_cache::{ImageCache, PendingImageId};
use net_traits::request::{Destination, RequestInit as FetchRequestInit};
use net_traits::{FetchMetadata, FetchResponseListener, FetchResponseMsg, NetworkError};
use net_traits::{ResourceFetchTiming, ResourceTimingType};
use servo_url::ServoUrl;
use std::sync::{Arc, Mutex};

struct LayoutImageContext {
    id: PendingImageId,
    cache: Arc<dyn ImageCache>,
    resource_timing: ResourceFetchTiming,
    doc: Trusted<Document>,
}

impl FetchResponseListener for LayoutImageContext {
    fn process_request_body(&mut self) {}
    fn process_request_eof(&mut self) {}
    fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>) {
        self.cache
            .notify_pending_response(self.id, FetchResponseMsg::ProcessResponse(metadata));
    }

    fn process_response_chunk(&mut self, payload: Vec<u8>) {
        self.cache
            .notify_pending_response(self.id, FetchResponseMsg::ProcessResponseChunk(payload));
    }

    fn process_response_eof(&mut self, response: Result<ResourceFetchTiming, NetworkError>) {
        self.cache
            .notify_pending_response(self.id, FetchResponseMsg::ProcessResponseEOF(response));
    }

    fn resource_timing_mut(&mut self) -> &mut ResourceFetchTiming {
        &mut self.resource_timing
    }

    fn resource_timing(&self) -> &ResourceFetchTiming {
        &self.resource_timing
    }

    fn submit_resource_timing(&mut self) {
        network_listener::submit_timing(self)
    }
}

impl ResourceTimingListener for LayoutImageContext {
    fn resource_timing_information(&self) -> (InitiatorType, ServoUrl) {
        (
            InitiatorType::Other,
            self.resource_timing_global().get_url().clone(),
        )
    }

    fn resource_timing_global(&self) -> DomRoot<GlobalScope> {
        self.doc.root().global()
    }
}

impl PreInvoke for LayoutImageContext {}

pub fn fetch_image_for_layout(
    url: ServoUrl,
    node: &Node,
    id: PendingImageId,
    cache: Arc<dyn ImageCache>,
) {
    let document = document_from_node(node);

    let context = Arc::new(Mutex::new(LayoutImageContext {
        id: id,
        cache: cache,
        resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
        doc: Trusted::new(&document),
    }));

    let document = document_from_node(node);

    let (action_sender, action_receiver) = ipc::channel().unwrap();
    let (task_source, canceller) = document
        .window()
        .task_manager()
        .networking_task_source_with_canceller();
    let listener = NetworkListener {
        context,
        task_source,
        canceller: Some(canceller),
    };
    ROUTER.add_route(
        action_receiver.to_opaque(),
        Box::new(move |message| {
            listener.notify_fetch(message.to().unwrap());
        }),
    );

    let request = FetchRequestInit {
        url: url,
        origin: document.origin().immutable().clone(),
        destination: Destination::Image,
        pipeline_id: Some(document.global().pipeline_id()),
        ..FetchRequestInit::default()
    };

    // Layout image loads do not delay the document load event.
    document
        .loader_mut()
        .fetch_async_background(request, action_sender);
}
<commit_msg>Auto merge of #23048 - c410-f3r:image-url, 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 https://mozilla.org/MPL/2.0/. */

//! Infrastructure to initiate network requests for images needed by the layout
//! thread. The script thread needs to be responsible for them because there's
//! no guarantee that the responsible nodes will still exist in the future if the
//! layout thread holds on to them during asynchronous operations.

use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::root::DomRoot;
use crate::dom::document::Document;
use crate::dom::globalscope::GlobalScope;
use crate::dom::node::{document_from_node, Node};
use crate::dom::performanceresourcetiming::InitiatorType;
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use net_traits::image_cache::{ImageCache, PendingImageId};
use net_traits::request::{Destination, RequestInit as FetchRequestInit};
use net_traits::{FetchMetadata, FetchResponseListener, FetchResponseMsg, NetworkError};
use net_traits::{ResourceFetchTiming, ResourceTimingType};
use servo_url::ServoUrl;
use std::sync::{Arc, Mutex};

struct LayoutImageContext {
    id: PendingImageId,
    cache: Arc<dyn ImageCache>,
    resource_timing: ResourceFetchTiming,
    doc: Trusted<Document>,
    url: ServoUrl,
}

impl FetchResponseListener for LayoutImageContext {
    fn process_request_body(&mut self) {}
    fn process_request_eof(&mut self) {}
    fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>) {
        self.cache
            .notify_pending_response(self.id, FetchResponseMsg::ProcessResponse(metadata));
    }

    fn process_response_chunk(&mut self, payload: Vec<u8>) {
        self.cache
            .notify_pending_response(self.id, FetchResponseMsg::ProcessResponseChunk(payload));
    }

    fn process_response_eof(&mut self, response: Result<ResourceFetchTiming, NetworkError>) {
        self.cache
            .notify_pending_response(self.id, FetchResponseMsg::ProcessResponseEOF(response));
    }

    fn resource_timing_mut(&mut self) -> &mut ResourceFetchTiming {
        &mut self.resource_timing
    }

    fn resource_timing(&self) -> &ResourceFetchTiming {
        &self.resource_timing
    }

    fn submit_resource_timing(&mut self) {
        network_listener::submit_timing(self)
    }
}

impl ResourceTimingListener for LayoutImageContext {
    fn resource_timing_information(&self) -> (InitiatorType, ServoUrl) {
        (InitiatorType::Other, self.url.clone())
    }

    fn resource_timing_global(&self) -> DomRoot<GlobalScope> {
        self.doc.root().global()
    }
}

impl PreInvoke for LayoutImageContext {}

pub fn fetch_image_for_layout(
    url: ServoUrl,
    node: &Node,
    id: PendingImageId,
    cache: Arc<dyn ImageCache>,
) {
    let document = document_from_node(node);

    let context = Arc::new(Mutex::new(LayoutImageContext {
        id: id,
        cache: cache,
        resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
        doc: Trusted::new(&document),
        url: url.clone(),
    }));

    let document = document_from_node(node);

    let (action_sender, action_receiver) = ipc::channel().unwrap();
    let (task_source, canceller) = document
        .window()
        .task_manager()
        .networking_task_source_with_canceller();
    let listener = NetworkListener {
        context,
        task_source,
        canceller: Some(canceller),
    };
    ROUTER.add_route(
        action_receiver.to_opaque(),
        Box::new(move |message| {
            listener.notify_fetch(message.to().unwrap());
        }),
    );

    let request = FetchRequestInit {
        url: url,
        origin: document.origin().immutable().clone(),
        destination: Destination::Image,
        pipeline_id: Some(document.global().pipeline_id()),
        ..FetchRequestInit::default()
    };

    // Layout image loads do not delay the document load event.
    document
        .loader_mut()
        .fetch_async_background(request, action_sender);
}
<|endoftext|>


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

// no-pretty-expanded unnecessary unsafe block generated
// ignore-lexer-test FIXME #15679

#![deny(warnings)]
#![allow(unused_must_use)]
#![allow(unknown_features)]
#![feature(box_syntax)]

use std::fmt;

struct A;
struct B;
struct C;

impl fmt::LowerHex for A {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("aloha")
    }
}
impl fmt::UpperHex for B {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("adios")
    }
}
impl fmt::Display for C {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad_integral(true, "☃", "123")
    }
}

macro_rules! t {
    ($a:expr, $b:expr) => { assert_eq!($a, $b) }
}

pub fn main() {
    // Various edge cases without formats
    t!(format!(""), "");
    t!(format!("hello"), "hello");
    t!(format!("hello {{"), "hello {");

    // default formatters should work
    t!(format!("{}", 1.0f32), "1");
    t!(format!("{}", 1.0f64), "1");
    t!(format!("{}", "a"), "a");
    t!(format!("{}", "a".to_string()), "a");
    t!(format!("{}", false), "false");
    t!(format!("{}", 'a'), "a");

    // At least exercise all the formats
    t!(format!("{}", true), "true");
    t!(format!("{}", '☃'), "☃");
    t!(format!("{}", 10), "10");
    t!(format!("{}", 10_usize), "10");
    t!(format!("{:?}", '☃'), "'\\u{2603}'");
    t!(format!("{:?}", 10), "10");
    t!(format!("{:?}", 10_usize), "10");
    t!(format!("{:?}", "true"), "\"true\"");
    t!(format!("{:?}", "foo\nbar"), "\"foo\\nbar\"");
    t!(format!("{:o}", 10_usize), "12");
    t!(format!("{:x}", 10_usize), "a");
    t!(format!("{:X}", 10_usize), "A");
    t!(format!("{}", "foo"), "foo");
    t!(format!("{}", "foo".to_string()), "foo");
    t!(format!("{:p}", 0x1234 as *const isize), "0x1234");
    t!(format!("{:p}", 0x1234 as *mut isize), "0x1234");
    t!(format!("{:x}", A), "aloha");
    t!(format!("{:X}", B), "adios");
    t!(format!("foo {} ☃☃☃☃☃☃", "bar"), "foo bar ☃☃☃☃☃☃");
    t!(format!("{1} {0}", 0, 1), "1 0");
    t!(format!("{foo} {bar}", foo=0, bar=1), "0 1");
    t!(format!("{foo} {1} {bar} {0}", 0, 1, foo=2, bar=3), "2 1 3 0");
    t!(format!("{} {0}", "a"), "a a");
    t!(format!("{foo_bar}", foo_bar=1), "1");
    t!(format!("{}", 5 + 5), "10");
    t!(format!("{:#4}", C), "☃123");

    // FIXME(#20676)
    // let a: &fmt::Debug = &1;
    // t!(format!("{:?}", a), "1");

    // Formatting strings and their arguments
    t!(format!("{}", "a"), "a");
    t!(format!("{:4}", "a"), "a   ");
    t!(format!("{:4}", "☃"), "☃   ");
    t!(format!("{:>4}", "a"), "   a");
    t!(format!("{:<4}", "a"), "a   ");
    t!(format!("{:^5}", "a"),  "  a  ");
    t!(format!("{:^5}", "aa"), " aa  ");
    t!(format!("{:^4}", "a"),  " a  ");
    t!(format!("{:^4}", "aa"), " aa ");
    t!(format!("{:.4}", "a"), "a");
    t!(format!("{:4.4}", "a"), "a   ");
    t!(format!("{:4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:<4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:>4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:^4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:>10.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:2.4}", "aaaaa"), "aaaa");
    t!(format!("{:2.4}", "aaaa"), "aaaa");
    t!(format!("{:2.4}", "aaa"), "aaa");
    t!(format!("{:2.4}", "aa"), "aa");
    t!(format!("{:2.4}", "a"), "a ");
    t!(format!("{:0>2}", "a"), "0a");
    t!(format!("{:.*}", 4, "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:.1$}", "aaaaaaaaaaaaaaaaaa", 4), "aaaa");
    t!(format!("{:.a$}", "aaaaaaaaaaaaaaaaaa", a=4), "aaaa");
    t!(format!("{:1$}", "a", 4), "a   ");
    t!(format!("{1:0$}", 4, "a"), "a   ");
    t!(format!("{:a$}", "a", a=4), "a   ");
    t!(format!("{:-#}", "a"), "a");
    t!(format!("{:+#}", "a"), "a");

    // Some float stuff
    t!(format!("{:}", 1.0f32), "1");
    t!(format!("{:}", 1.0f64), "1");
    t!(format!("{:.3}", 1.0f64), "1.000");
    t!(format!("{:10.3}", 1.0f64),   "     1.000");
    t!(format!("{:+10.3}", 1.0f64),  "    +1.000");
    t!(format!("{:+10.3}", -1.0f64), "    -1.000");

    t!(format!("{:e}", 1.2345e6f32), "1.2345e6");
    t!(format!("{:e}", 1.2345e6f64), "1.2345e6");
    t!(format!("{:E}", 1.2345e6f64), "1.2345E6");
    t!(format!("{:.3e}", 1.2345e6f64), "1.234e6");
    t!(format!("{:10.3e}", 1.2345e6f64),   "   1.234e6");
    t!(format!("{:+10.3e}", 1.2345e6f64),  "  +1.234e6");
    t!(format!("{:+10.3e}", -1.2345e6f64), "  -1.234e6");

    // Test that pointers don't get truncated.
    {
        let val = usize::MAX;
        let exp = format!("{:#x}", val);
        t!(format!("{:p}", val as *const isize), exp);
    }

    // Escaping
    t!(format!("{{"), "{");
    t!(format!("}}"), "}");

    test_write();
    test_print();
    test_order();

    // make sure that format! doesn't move out of local variables
    let a = box 3;
    format!("{}", a);
    format!("{}", a);

    // make sure that format! doesn't cause spurious unused-unsafe warnings when
    // it's inside of an outer unsafe block
    unsafe {
        let a: isize = ::std::mem::transmute(3_usize);
        format!("{}", a);
    }

    test_format_args();

    // test that trailing commas are acceptable
    format!("{}", "test",);
    format!("{foo}", foo="test",);
}

// Basic test to make sure that we can invoke the `write!` macro with an
// fmt::Write instance.
fn test_write() {
    use std::fmt::Write;
    let mut buf = String::new();
    write!(&mut buf, "{}", 3);
    {
        let w = &mut buf;
        write!(w, "{foo}", foo=4);
        write!(w, "{}", "hello");
        writeln!(w, "{}", "line");
        writeln!(w, "{foo}", foo="bar");
    }

    t!(buf, "34helloline\nbar\n");
}

// Just make sure that the macros are defined, there's not really a lot that we
// can do with them just yet (to test the output)
fn test_print() {
    print!("hi");
    print!("{:?}", vec!(0u8));
    println!("hello");
    println!("this is a {}", "test");
    println!("{foo}", foo="bar");
}

// Just make sure that the macros are defined, there's not really a lot that we
// can do with them just yet (to test the output)
fn test_format_args() {
    use std::fmt::Write;
    let mut buf = String::new();
    {
        let w = &mut buf;
        write!(w, "{}", format_args!("{}", 1));
        write!(w, "{}", format_args!("test"));
        write!(w, "{}", format_args!("{test}", test=3));
    }
    let s = buf;
    t!(s, "1test3");

    let s = fmt::format(format_args!("hello {}", "world"));
    t!(s, "hello world");
    let s = format!("{}: {}", "args were", format_args!("hello {}", "world"));
    t!(s, "args were: hello world");
}

fn test_order() {
    // Make sure format!() arguments are always evaluated in a left-to-right
    // ordering
    fn foo() -> isize {
        static mut FOO: isize = 0;
        unsafe {
            FOO += 1;
            FOO
        }
    }
    assert_eq!(format!("{} {} {a} {b} {} {c}",
                       foo(), foo(), foo(), a=foo(), b=foo(), c=foo()),
               "1 2 4 5 3 6".to_string());
}
<commit_msg>Add import of usize (fixup #22901)<commit_after>// Copyright 2014 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.

// no-pretty-expanded unnecessary unsafe block generated
// ignore-lexer-test FIXME #15679

#![deny(warnings)]
#![allow(unused_must_use)]
#![allow(unknown_features)]
#![feature(box_syntax)]

use std::fmt;
use std::usize;

struct A;
struct B;
struct C;

impl fmt::LowerHex for A {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("aloha")
    }
}
impl fmt::UpperHex for B {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("adios")
    }
}
impl fmt::Display for C {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad_integral(true, "☃", "123")
    }
}

macro_rules! t {
    ($a:expr, $b:expr) => { assert_eq!($a, $b) }
}

pub fn main() {
    // Various edge cases without formats
    t!(format!(""), "");
    t!(format!("hello"), "hello");
    t!(format!("hello {{"), "hello {");

    // default formatters should work
    t!(format!("{}", 1.0f32), "1");
    t!(format!("{}", 1.0f64), "1");
    t!(format!("{}", "a"), "a");
    t!(format!("{}", "a".to_string()), "a");
    t!(format!("{}", false), "false");
    t!(format!("{}", 'a'), "a");

    // At least exercise all the formats
    t!(format!("{}", true), "true");
    t!(format!("{}", '☃'), "☃");
    t!(format!("{}", 10), "10");
    t!(format!("{}", 10_usize), "10");
    t!(format!("{:?}", '☃'), "'\\u{2603}'");
    t!(format!("{:?}", 10), "10");
    t!(format!("{:?}", 10_usize), "10");
    t!(format!("{:?}", "true"), "\"true\"");
    t!(format!("{:?}", "foo\nbar"), "\"foo\\nbar\"");
    t!(format!("{:o}", 10_usize), "12");
    t!(format!("{:x}", 10_usize), "a");
    t!(format!("{:X}", 10_usize), "A");
    t!(format!("{}", "foo"), "foo");
    t!(format!("{}", "foo".to_string()), "foo");
    t!(format!("{:p}", 0x1234 as *const isize), "0x1234");
    t!(format!("{:p}", 0x1234 as *mut isize), "0x1234");
    t!(format!("{:x}", A), "aloha");
    t!(format!("{:X}", B), "adios");
    t!(format!("foo {} ☃☃☃☃☃☃", "bar"), "foo bar ☃☃☃☃☃☃");
    t!(format!("{1} {0}", 0, 1), "1 0");
    t!(format!("{foo} {bar}", foo=0, bar=1), "0 1");
    t!(format!("{foo} {1} {bar} {0}", 0, 1, foo=2, bar=3), "2 1 3 0");
    t!(format!("{} {0}", "a"), "a a");
    t!(format!("{foo_bar}", foo_bar=1), "1");
    t!(format!("{}", 5 + 5), "10");
    t!(format!("{:#4}", C), "☃123");

    // FIXME(#20676)
    // let a: &fmt::Debug = &1;
    // t!(format!("{:?}", a), "1");

    // Formatting strings and their arguments
    t!(format!("{}", "a"), "a");
    t!(format!("{:4}", "a"), "a   ");
    t!(format!("{:4}", "☃"), "☃   ");
    t!(format!("{:>4}", "a"), "   a");
    t!(format!("{:<4}", "a"), "a   ");
    t!(format!("{:^5}", "a"),  "  a  ");
    t!(format!("{:^5}", "aa"), " aa  ");
    t!(format!("{:^4}", "a"),  " a  ");
    t!(format!("{:^4}", "aa"), " aa ");
    t!(format!("{:.4}", "a"), "a");
    t!(format!("{:4.4}", "a"), "a   ");
    t!(format!("{:4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:<4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:>4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:^4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:>10.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:2.4}", "aaaaa"), "aaaa");
    t!(format!("{:2.4}", "aaaa"), "aaaa");
    t!(format!("{:2.4}", "aaa"), "aaa");
    t!(format!("{:2.4}", "aa"), "aa");
    t!(format!("{:2.4}", "a"), "a ");
    t!(format!("{:0>2}", "a"), "0a");
    t!(format!("{:.*}", 4, "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:.1$}", "aaaaaaaaaaaaaaaaaa", 4), "aaaa");
    t!(format!("{:.a$}", "aaaaaaaaaaaaaaaaaa", a=4), "aaaa");
    t!(format!("{:1$}", "a", 4), "a   ");
    t!(format!("{1:0$}", 4, "a"), "a   ");
    t!(format!("{:a$}", "a", a=4), "a   ");
    t!(format!("{:-#}", "a"), "a");
    t!(format!("{:+#}", "a"), "a");

    // Some float stuff
    t!(format!("{:}", 1.0f32), "1");
    t!(format!("{:}", 1.0f64), "1");
    t!(format!("{:.3}", 1.0f64), "1.000");
    t!(format!("{:10.3}", 1.0f64),   "     1.000");
    t!(format!("{:+10.3}", 1.0f64),  "    +1.000");
    t!(format!("{:+10.3}", -1.0f64), "    -1.000");

    t!(format!("{:e}", 1.2345e6f32), "1.2345e6");
    t!(format!("{:e}", 1.2345e6f64), "1.2345e6");
    t!(format!("{:E}", 1.2345e6f64), "1.2345E6");
    t!(format!("{:.3e}", 1.2345e6f64), "1.234e6");
    t!(format!("{:10.3e}", 1.2345e6f64),   "   1.234e6");
    t!(format!("{:+10.3e}", 1.2345e6f64),  "  +1.234e6");
    t!(format!("{:+10.3e}", -1.2345e6f64), "  -1.234e6");

    // Test that pointers don't get truncated.
    {
        let val = usize::MAX;
        let exp = format!("{:#x}", val);
        t!(format!("{:p}", val as *const isize), exp);
    }

    // Escaping
    t!(format!("{{"), "{");
    t!(format!("}}"), "}");

    test_write();
    test_print();
    test_order();

    // make sure that format! doesn't move out of local variables
    let a = box 3;
    format!("{}", a);
    format!("{}", a);

    // make sure that format! doesn't cause spurious unused-unsafe warnings when
    // it's inside of an outer unsafe block
    unsafe {
        let a: isize = ::std::mem::transmute(3_usize);
        format!("{}", a);
    }

    test_format_args();

    // test that trailing commas are acceptable
    format!("{}", "test",);
    format!("{foo}", foo="test",);
}

// Basic test to make sure that we can invoke the `write!` macro with an
// fmt::Write instance.
fn test_write() {
    use std::fmt::Write;
    let mut buf = String::new();
    write!(&mut buf, "{}", 3);
    {
        let w = &mut buf;
        write!(w, "{foo}", foo=4);
        write!(w, "{}", "hello");
        writeln!(w, "{}", "line");
        writeln!(w, "{foo}", foo="bar");
    }

    t!(buf, "34helloline\nbar\n");
}

// Just make sure that the macros are defined, there's not really a lot that we
// can do with them just yet (to test the output)
fn test_print() {
    print!("hi");
    print!("{:?}", vec!(0u8));
    println!("hello");
    println!("this is a {}", "test");
    println!("{foo}", foo="bar");
}

// Just make sure that the macros are defined, there's not really a lot that we
// can do with them just yet (to test the output)
fn test_format_args() {
    use std::fmt::Write;
    let mut buf = String::new();
    {
        let w = &mut buf;
        write!(w, "{}", format_args!("{}", 1));
        write!(w, "{}", format_args!("test"));
        write!(w, "{}", format_args!("{test}", test=3));
    }
    let s = buf;
    t!(s, "1test3");

    let s = fmt::format(format_args!("hello {}", "world"));
    t!(s, "hello world");
    let s = format!("{}: {}", "args were", format_args!("hello {}", "world"));
    t!(s, "args were: hello world");
}

fn test_order() {
    // Make sure format!() arguments are always evaluated in a left-to-right
    // ordering
    fn foo() -> isize {
        static mut FOO: isize = 0;
        unsafe {
            FOO += 1;
            FOO
        }
    }
    assert_eq!(format!("{} {} {a} {b} {} {c}",
                       foo(), foo(), foo(), a=foo(), b=foo(), c=foo()),
               "1 2 4 5 3 6".to_string());
}
<|endoftext|>


<commit_before>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2014  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use types::{gpointer,gconstpointer};
use std::kinds::marker;

pub type RefFunc = unsafe extern "C" fn(gpointer) -> gpointer;
pub type UnrefFunc = unsafe extern "C" fn(gpointer);
pub type RefcountFuncs = (*const RefFunc, *const UnrefFunc);

pub trait Refcount {
    fn refcount_funcs(&self) -> &'static RefcountFuncs;
}

pub struct Ref<T: Refcount> {
    plumbing: RefImpl,
    no_send: marker::NoSend,
    no_sync: marker::NoSync
}

pub struct SyncRef<T: Refcount + Send + Sync> {
    plumbing: RefImpl
}

impl<T: Refcount> Ref<T> {
    pub fn new(source: &mut T) -> Ref<T> {
        unsafe { make_ref(source as *mut T) }
    }

    pub fn borrow<'a>(&'a self) -> &'a T {
        unsafe { &*self.raw_ptr() }
    }
    pub fn borrow_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe { &mut *self.raw_mut_ptr() }
    }

    pub fn raw_ptr(&self) -> *const T {
        self.plumbing.ptr as gconstpointer as *const T
    }
    pub fn raw_mut_ptr(&mut self) -> *mut T {
        self.plumbing.ptr as *mut T
    }
}

impl<T: Refcount + Send + Sync> SyncRef<T> {
    pub fn new(source: &mut T) -> SyncRef<T> {
        unsafe { make_sync_ref(source as *mut T) }
    }

    pub fn borrow<'a>(&'a self) -> &'a T {
        unsafe { &*self.raw_ptr() }
    }
    pub fn borrow_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe { &mut *self.raw_mut_ptr() }
    }

    pub fn raw_ptr(&self) -> *const T {
        self.plumbing.ptr as gconstpointer as *const T
    }
    pub fn raw_mut_ptr(&mut self) -> *mut T {
        self.plumbing.ptr as *mut T
    }
}

pub mod raw {

    use super::{Refcount,RefImpl,Ref,SyncRef};
    use types::gpointer;
    use std::kinds::marker;

    pub unsafe fn ref_from_ptr<T: Refcount>(p: *mut T) -> Ref<T> {
        Ref {
            plumbing: RefImpl::from_ptr(p as gpointer),
            no_send: marker::NoSend,
            no_sync: marker::NoSync
        }
    }

    pub unsafe fn sync_ref_from_ptr<T: Refcount + Send + Sync>(p: *mut T)
                                                             -> SyncRef<T> {
        SyncRef {
            plumbing: RefImpl::from_ptr(p as gpointer)
        }
    }
}

struct RefImpl {
    ptr: gpointer
}

impl RefImpl {
    fn from_ptr(p: gpointer) -> RefImpl {
        RefImpl { ptr: p }
    }

    unsafe fn impl_drop(&mut self, (_, dec_ref): RefcountFuncs) {
        (*dec_ref)(self.ptr);
    }

    unsafe fn impl_clone_from(&mut self, source: &RefImpl,
                              (inc_ref, dec_ref): RefcountFuncs) {
        (*inc_ref)(source.ptr);
        (*dec_ref)(self.ptr);
        self.ptr = source.ptr;
    }
}

unsafe fn make_ref_impl(p: gpointer, (inc_ref, _): RefcountFuncs) -> RefImpl {
    (*inc_ref)(p);
    RefImpl::from_ptr(p)
}

pub unsafe fn make_ref<T: Refcount>(p: *mut T) -> Ref<T> {
    Ref {
        plumbing: make_ref_impl(p as gpointer, *(*p).refcount_funcs()),
        no_send: marker::NoSend,
        no_sync: marker::NoSync
    }
}

pub unsafe fn make_sync_ref<T: Refcount + Send + Sync>(p: *mut T) -> SyncRef<T> {
    SyncRef {
        plumbing: make_ref_impl(p as gpointer, *(*p).refcount_funcs())
    }
}

#[unsafe_destructor]
impl<T: Refcount> Drop for Ref<T> {
    fn drop(&mut self) {
        unsafe {
            let funcs = (*self.raw_ptr()).refcount_funcs();
            self.plumbing.impl_drop(*funcs);
        }
    }
}

#[unsafe_destructor]
impl<T: Refcount + Send + Sync> Drop for SyncRef<T> {
    fn drop(&mut self) {
        unsafe {
            let funcs = (*self.raw_ptr()).refcount_funcs();
            self.plumbing.impl_drop(*funcs);
        }
    }
}

impl<T: Refcount> Clone for Ref<T> {

    fn clone(&self) -> Ref<T> {
        unsafe { make_ref(self.raw_ptr() as *mut T) }
    }

    fn clone_from(&mut self, source: &Ref<T>) {
        unsafe {
            let funcs = (*self.raw_ptr()).refcount_funcs();
            self.plumbing.impl_clone_from(&source.plumbing, *funcs);
        }
    }
}

impl<T: Refcount + Send + Sync> Clone for SyncRef<T> {

    fn clone(&self) -> SyncRef<T> {
        unsafe { make_sync_ref(self.raw_ptr() as *mut T) }
    }

    fn clone_from(&mut self, source: &SyncRef<T>) {
        unsafe {
            let funcs = (*self.raw_ptr()).refcount_funcs();
            self.plumbing.impl_clone_from(&source.plumbing, *funcs);
        }
    }
}

impl<T: Refcount> Deref<T> for Ref<T> {
    fn deref<'a>(&'a self) -> &'a T {
        unsafe { &*self.raw_ptr() }
    }
}

impl<T: Refcount + Send + Sync> Deref<T> for SyncRef<T> {
    fn deref<'a>(&'a self) -> &'a T {
        unsafe { &*self.raw_ptr() }
    }
}

impl<T: Refcount> DerefMut<T> for Ref<T> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe { &mut *self.raw_mut_ptr() }
    }
}

impl<T: Refcount + Send + Sync> DerefMut<T> for SyncRef<T> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe { &mut *self.raw_mut_ptr() }
    }
}
<commit_msg>No mutability requirement on self to get the raw mut pointer<commit_after>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2014  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use types::{gpointer,gconstpointer};
use std::kinds::marker;

pub type RefFunc = unsafe extern "C" fn(gpointer) -> gpointer;
pub type UnrefFunc = unsafe extern "C" fn(gpointer);
pub type RefcountFuncs = (*const RefFunc, *const UnrefFunc);

pub trait Refcount {
    fn refcount_funcs(&self) -> &'static RefcountFuncs;
}

pub struct Ref<T: Refcount> {
    plumbing: RefImpl,
    no_send: marker::NoSend,
    no_sync: marker::NoSync
}

pub struct SyncRef<T: Refcount + Send + Sync> {
    plumbing: RefImpl
}

impl<T: Refcount> Ref<T> {
    pub fn new(source: &mut T) -> Ref<T> {
        unsafe { make_ref(source as *mut T) }
    }

    pub fn borrow<'a>(&'a self) -> &'a T {
        unsafe { &*self.raw_ptr() }
    }
    pub fn borrow_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe { &mut *self.raw_mut_ptr() }
    }

    pub fn raw_ptr(&self) -> *const T {
        self.plumbing.ptr as gconstpointer as *const T
    }
    pub fn raw_mut_ptr(&self) -> *mut T {
        self.plumbing.ptr as *mut T
    }
}

impl<T: Refcount + Send + Sync> SyncRef<T> {
    pub fn new(source: &mut T) -> SyncRef<T> {
        unsafe { make_sync_ref(source as *mut T) }
    }

    pub fn borrow<'a>(&'a self) -> &'a T {
        unsafe { &*self.raw_ptr() }
    }
    pub fn borrow_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe { &mut *self.raw_mut_ptr() }
    }

    pub fn raw_ptr(&self) -> *const T {
        self.plumbing.ptr as gconstpointer as *const T
    }
    pub fn raw_mut_ptr(&self) -> *mut T {
        self.plumbing.ptr as *mut T
    }
}

pub mod raw {

    use super::{Refcount,RefImpl,Ref,SyncRef};
    use types::gpointer;
    use std::kinds::marker;

    pub unsafe fn ref_from_ptr<T: Refcount>(p: *mut T) -> Ref<T> {
        Ref {
            plumbing: RefImpl::from_ptr(p as gpointer),
            no_send: marker::NoSend,
            no_sync: marker::NoSync
        }
    }

    pub unsafe fn sync_ref_from_ptr<T: Refcount + Send + Sync>(p: *mut T)
                                                             -> SyncRef<T> {
        SyncRef {
            plumbing: RefImpl::from_ptr(p as gpointer)
        }
    }
}

struct RefImpl {
    ptr: gpointer
}

impl RefImpl {
    fn from_ptr(p: gpointer) -> RefImpl {
        RefImpl { ptr: p }
    }

    unsafe fn impl_drop(&mut self, (_, dec_ref): RefcountFuncs) {
        (*dec_ref)(self.ptr);
    }

    unsafe fn impl_clone_from(&mut self, source: &RefImpl,
                              (inc_ref, dec_ref): RefcountFuncs) {
        (*inc_ref)(source.ptr);
        (*dec_ref)(self.ptr);
        self.ptr = source.ptr;
    }
}

unsafe fn make_ref_impl(p: gpointer, (inc_ref, _): RefcountFuncs) -> RefImpl {
    (*inc_ref)(p);
    RefImpl::from_ptr(p)
}

pub unsafe fn make_ref<T: Refcount>(p: *mut T) -> Ref<T> {
    Ref {
        plumbing: make_ref_impl(p as gpointer, *(*p).refcount_funcs()),
        no_send: marker::NoSend,
        no_sync: marker::NoSync
    }
}

pub unsafe fn make_sync_ref<T: Refcount + Send + Sync>(p: *mut T) -> SyncRef<T> {
    SyncRef {
        plumbing: make_ref_impl(p as gpointer, *(*p).refcount_funcs())
    }
}

#[unsafe_destructor]
impl<T: Refcount> Drop for Ref<T> {
    fn drop(&mut self) {
        unsafe {
            let funcs = (*self.raw_ptr()).refcount_funcs();
            self.plumbing.impl_drop(*funcs);
        }
    }
}

#[unsafe_destructor]
impl<T: Refcount + Send + Sync> Drop for SyncRef<T> {
    fn drop(&mut self) {
        unsafe {
            let funcs = (*self.raw_ptr()).refcount_funcs();
            self.plumbing.impl_drop(*funcs);
        }
    }
}

impl<T: Refcount> Clone for Ref<T> {

    fn clone(&self) -> Ref<T> {
        unsafe { make_ref(self.raw_ptr() as *mut T) }
    }

    fn clone_from(&mut self, source: &Ref<T>) {
        unsafe {
            let funcs = (*self.raw_ptr()).refcount_funcs();
            self.plumbing.impl_clone_from(&source.plumbing, *funcs);
        }
    }
}

impl<T: Refcount + Send + Sync> Clone for SyncRef<T> {

    fn clone(&self) -> SyncRef<T> {
        unsafe { make_sync_ref(self.raw_ptr() as *mut T) }
    }

    fn clone_from(&mut self, source: &SyncRef<T>) {
        unsafe {
            let funcs = (*self.raw_ptr()).refcount_funcs();
            self.plumbing.impl_clone_from(&source.plumbing, *funcs);
        }
    }
}

impl<T: Refcount> Deref<T> for Ref<T> {
    fn deref<'a>(&'a self) -> &'a T {
        unsafe { &*self.raw_ptr() }
    }
}

impl<T: Refcount + Send + Sync> Deref<T> for SyncRef<T> {
    fn deref<'a>(&'a self) -> &'a T {
        unsafe { &*self.raw_ptr() }
    }
}

impl<T: Refcount> DerefMut<T> for Ref<T> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe { &mut *self.raw_mut_ptr() }
    }
}

impl<T: Refcount + Send + Sync> DerefMut<T> for SyncRef<T> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe { &mut *self.raw_mut_ptr() }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use libra_metrics::{
    register_histogram, register_int_counter, register_int_counter_vec, Histogram, IntCounter,
    IntCounterVec,
};
use once_cell::sync::Lazy;

/// Count the number of transactions validated, with a "status" label to
/// distinguish success or failure results.
pub static TRANSACTIONS_VALIDATED: Lazy<IntCounterVec> = Lazy::new(|| {
    register_int_counter_vec!(
        "libra_vm_transactions_validated",
        "Number of transactions validated",
        &["status"]
    )
    .unwrap()
});

/// Count the number of user transactions executed, with a "status" label to
/// distinguish completed vs. discarded transactions.
pub static USER_TRANSACTIONS_EXECUTED: Lazy<IntCounterVec> = Lazy::new(|| {
    register_int_counter_vec!(
        "libra_vm_user_transactions_executed",
        "Number of user transactions executed",
        &["status"]
    )
    .unwrap()
});

/// Count the number of system transactions executed.
pub static SYSTEM_TRANSACTIONS_EXECUTED: Lazy<IntCounter> = Lazy::new(|| {
    register_int_counter!(
        "libra_vm_system_transactions_executed",
        "Number of system transactions executed"
    )
    .unwrap()
});

pub static BLOCK_TRANSACTION_COUNT: Lazy<Histogram> = Lazy::new(|| {
    register_histogram!(
        "libra_vm_block_transaction_count",
        "Number of transaction per block"
    )
    .unwrap()
});

pub static TXN_TOTAL_SECONDS: Lazy<Histogram> = Lazy::new(|| {
    register_histogram!(
        "libra_vm_txn_total_seconds",
        "Histogram of total time per transaction"
    )
    .unwrap()
});

pub static TXN_VALIDATION_SECONDS: Lazy<Histogram> = Lazy::new(|| {
    register_histogram!(
        "libra_vm_txn_validation_seconds",
        "Histogram of validation time per transaction"
    )
    .unwrap()
});

pub static TXN_GAS_USAGE: Lazy<Histogram> = Lazy::new(|| {
    register_histogram!(
        "libra_vm_txn_gas_usage",
        "Histogram for the gas used for txns"
    )
    .unwrap()
});

/// Count the number of critical errors. This is not intended for display
/// on a dashboard but rather for triggering alerts.
pub static CRITICAL_ERRORS: Lazy<IntCounter> = Lazy::new(|| {
    register_int_counter!("libra_vm_critical_errors", "Number of critical errors").unwrap()
});
<commit_msg>[vm] adjust name of block size metric and improve some metric descriptions<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use libra_metrics::{
    register_histogram, register_int_counter, register_int_counter_vec, Histogram, IntCounter,
    IntCounterVec,
};
use once_cell::sync::Lazy;

/// Count the number of transactions validated, with a "status" label to
/// distinguish success or failure results.
pub static TRANSACTIONS_VALIDATED: Lazy<IntCounterVec> = Lazy::new(|| {
    register_int_counter_vec!(
        "libra_vm_transactions_validated",
        "Number of transactions validated",
        &["status"]
    )
    .unwrap()
});

/// Count the number of user transactions executed, with a "status" label to
/// distinguish completed vs. discarded transactions.
pub static USER_TRANSACTIONS_EXECUTED: Lazy<IntCounterVec> = Lazy::new(|| {
    register_int_counter_vec!(
        "libra_vm_user_transactions_executed",
        "Number of user transactions executed",
        &["status"]
    )
    .unwrap()
});

/// Count the number of system transactions executed.
pub static SYSTEM_TRANSACTIONS_EXECUTED: Lazy<IntCounter> = Lazy::new(|| {
    register_int_counter!(
        "libra_vm_system_transactions_executed",
        "Number of system transactions executed"
    )
    .unwrap()
});

pub static BLOCK_TRANSACTION_COUNT: Lazy<Histogram> = Lazy::new(|| {
    register_histogram!(
        "libra_vm_num_txns_per_block",
        "Number of transactions per block"
    )
    .unwrap()
});

pub static TXN_TOTAL_SECONDS: Lazy<Histogram> = Lazy::new(|| {
    register_histogram!(
        "libra_vm_txn_total_seconds",
        "Execution time per user transaction"
    )
    .unwrap()
});

pub static TXN_VALIDATION_SECONDS: Lazy<Histogram> = Lazy::new(|| {
    register_histogram!(
        "libra_vm_txn_validation_seconds",
        "Validation time per user transaction"
    )
    .unwrap()
});

pub static TXN_GAS_USAGE: Lazy<Histogram> = Lazy::new(|| {
    register_histogram!("libra_vm_txn_gas_usage", "Gas used per transaction").unwrap()
});

/// Count the number of critical errors. This is not intended for display
/// on a dashboard but rather for triggering alerts.
pub static CRITICAL_ERRORS: Lazy<IntCounter> = Lazy::new(|| {
    register_int_counter!("libra_vm_critical_errors", "Number of critical errors").unwrap()
});
<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! A tape is a symbol reader that can be rewound.
//!
//! It can be useful for matching a pattern repeatedly against an input, as the state machine may read many extra symbols
//! before it finds a match at an earlier position. To find another match after the first one, it's necessary to rewind
//! the stream.
//!
//! A tape implements `SymbolReader` so can be treated just like a normal symbol stream. However, it also adds two new methods.
//! `rewind` will go back a number of symbols (provided the tape contains that many symbols). `cut` removes any symbols prior
//! to the current one from the tape, making it impossible to rewind beyond the current point.
//!

use super::symbol_reader::*;

///
/// Rewindable symbol reader
///
pub struct Tape<Symbol: Sized, SourceReader: SymbolReader<Symbol>+Sized> {
    /// Symbol reader where items not in the buffer are read from
    read_from: SourceReader,

    /// Circular buffer where stored symbols are kept
    buffer: Vec<Option<Symbol>>,

    /// Next symbol to read from the buffer
    read_index: usize,

    /// Position of the last symbol in the buffer
    last_symbol_index: usize,

    /// Position of the first symbol in the buffer
    first_symbol_index: usize,

    /// True if the target reader has returned None
    end_of_reader: bool
}

impl<Symbol: Clone+Sized, SourceReader: SymbolReader<Symbol>> Tape<Symbol, SourceReader> {
    ///
    /// Creates a new tape from a symbol reader
    ///
    pub fn new(source: SourceReader) -> Tape<Symbol, SourceReader> {
        Tape { read_from: source, buffer: vec![None, None, None, None], read_index: 0, last_symbol_index: 0, first_symbol_index: 0, end_of_reader: false }
    }

    ///
    /// Resizes the buffer so that it can store at least one more symbol
    ///
    pub fn resize(&mut self) {
        let new_size        = self.buffer.len() * 2;
        let mut new_buffer  = Vec::with_capacity(new_size);

        // Copy all the occupied symbols from the old buffer
        let mut copy_index     = self.first_symbol_index;
        let mut new_read_index = 0;
        while copy_index != self.last_symbol_index {
            new_buffer.push(self.buffer[copy_index].clone());

            copy_index += 1;
            if copy_index >= self.buffer.len() { copy_index = 0; }

            if copy_index == self.read_index { new_read_index = new_buffer.len() }
        }

        // The current length is where the first 'new' symbol will go
        let new_last_symbol_index = new_buffer.len();

        // The rest of the buffer is filled with 'Nones'
        for _ in new_last_symbol_index..new_size {
            new_buffer.push(None);
        }

        // Replace the buffer
        self.buffer             = new_buffer;
        self.first_symbol_index = 0;
        self.last_symbol_index  = new_last_symbol_index;
        self.read_index         = new_read_index;
    }

    ///
    /// Trims the buffer so that it's not possible to rewind past the current read position
    ///
    pub fn cut(&mut self) {
        self.first_symbol_index = self.read_index;
    }

    ///
    /// Returns the number of symbols in the buffer
    ///
    #[inline]
    pub fn buffer_size(&mut self) -> usize {
        if self.first_symbol_index > self.last_symbol_index {
            (self.last_symbol_index + self.buffer.len()) - self.first_symbol_index
        } else {
            self.last_symbol_index - self.first_symbol_index
        }
    }

    ///
    /// Moves backwards by num_symbols
    ///
    pub fn rewind(&mut self, num_symbols: usize) {
        // Do nothing if we're over the maximum length of the buffer
        if num_symbols > self.buffer_size() {
            panic!("Can't rewind beyond the start of the tape");
        }

        // Move backwards num_symbols
        let mut new_read_index = (self.read_index+self.buffer.len()) - num_symbols;
        if new_read_index >= self.buffer.len() { new_read_index -= self.buffer.len(); }

        self.read_index = new_read_index;
    }
}

impl<Symbol: Clone+Sized, Reader: SymbolReader<Symbol>+Sized> SymbolReader<Symbol> for Tape<Symbol, Reader> {
    fn next_symbol(&mut self) -> Option<Symbol> {
        if self.read_index == self.last_symbol_index {
            // If the source reader has ended, there's nothing more to read
            if self.end_of_reader {
                return None;
            }

            // At end of buffer: need to fill it some more
            let maybe_symbol = self.read_from.next_symbol();
            match maybe_symbol {
                None => {
                    // Mark this stream as having finished (we won't read from the source stream any more)
                    self.end_of_reader = true;
                    return None;
                },

                _ => {
                    // Resize the buffer if needed
                    if (self.last_symbol_index+1)%self.buffer.len() == self.first_symbol_index {
                        self.resize();
                    }

                    // Store the next symbol (we'll immediately read it from the buffer later on)
                    self.buffer[self.last_symbol_index] = maybe_symbol;

                    self.last_symbol_index += 1;
                    if self.last_symbol_index >= self.buffer.len() { self.last_symbol_index = 0; }
                }
            }
        }

        // Result is whatever is in the buffer at the read position
        let result = self.buffer[self.read_index].clone();

        self.read_index += 1;
        if self.read_index >= self.buffer.len() { self.read_index = 0; }

        result
    }
}

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

    #[test]
    fn can_read_from_tape() {
        let source_vec    = vec![1,2,3,4,5,6];
        let source_stream = source_vec.read_symbols();
        let mut tape      = Tape::new(source_stream);

        assert!(tape.next_symbol() == Some(1));
        assert!(tape.next_symbol() == Some(2));
        assert!(tape.next_symbol() == Some(3));
        assert!(tape.next_symbol() == Some(4));
        assert!(tape.next_symbol() == Some(5));
        assert!(tape.next_symbol() == Some(6));
        assert!(tape.next_symbol() == None);
    }

    #[test]
    fn can_rewind_tape() {
        let source_vec    = vec![1,2,3,4,5,6];
        let source_stream = source_vec.read_symbols();
        let mut tape      = Tape::new(source_stream);

        assert!(tape.next_symbol() == Some(1));
        assert!(tape.next_symbol() == Some(2));
        assert!(tape.next_symbol() == Some(3));
        tape.rewind(3);

        assert!(tape.next_symbol() == Some(1));
        assert!(tape.next_symbol() == Some(2));
        assert!(tape.next_symbol() == Some(3));
        assert!(tape.next_symbol() == Some(4));
        assert!(tape.next_symbol() == Some(5));
        assert!(tape.next_symbol() == Some(6));
        assert!(tape.next_symbol() == None);

        tape.rewind(4);
        assert!(tape.next_symbol() == Some(3));
        assert!(tape.next_symbol() == Some(4));
        assert!(tape.next_symbol() == Some(5));
        assert!(tape.next_symbol() == Some(6));
        assert!(tape.next_symbol() == None);
    }

    #[test]
    fn can_cut_tape() {
        let source_vec    = vec![1,2,3,4,5,6,7,8,9];
        let source_stream = source_vec.read_symbols();
        let mut tape      = Tape::new(source_stream);

        assert!(tape.next_symbol() == Some(1));
        assert!(tape.next_symbol() == Some(2));
        assert!(tape.next_symbol() == Some(3));
        tape.cut();

        assert!(tape.next_symbol() == Some(4));
        assert!(tape.next_symbol() == Some(5));
        assert!(tape.next_symbol() == Some(6));
        tape.rewind(3);

        assert!(tape.next_symbol() == Some(4));
        assert!(tape.next_symbol() == Some(5));
        assert!(tape.next_symbol() == Some(6));
        assert!(tape.next_symbol() == Some(7));
        assert!(tape.next_symbol() == Some(8));
        assert!(tape.next_symbol() == Some(9));
        assert!(tape.next_symbol() == None);

        tape.rewind(3);
        tape.cut();
        assert!(tape.next_symbol() == Some(7));
        assert!(tape.next_symbol() == Some(8));
        assert!(tape.next_symbol() == Some(9));
        assert!(tape.next_symbol() == None);

        tape.rewind(2);
        assert!(tape.next_symbol() == Some(8));
        assert!(tape.next_symbol() == Some(9));
        assert!(tape.next_symbol() == None);
    }
}
<commit_msg>Add a way to get the position in the source when using a tape<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! A tape is a symbol reader that can be rewound.
//!
//! It can be useful for matching a pattern repeatedly against an input, as the state machine may read many extra symbols
//! before it finds a match at an earlier position. To find another match after the first one, it's necessary to rewind
//! the stream.
//!
//! A tape implements `SymbolReader` so can be treated just like a normal symbol stream. However, it also adds two new methods.
//! `rewind` will go back a number of symbols (provided the tape contains that many symbols). `cut` removes any symbols prior
//! to the current one from the tape, making it impossible to rewind beyond the current point.
//!

use super::symbol_reader::*;

///
/// Rewindable symbol reader
///
pub struct Tape<Symbol: Sized, SourceReader: SymbolReader<Symbol>+Sized> {
    /// Symbol reader where items not in the buffer are read from
    read_from: SourceReader,

    /// Circular buffer where stored symbols are kept
    buffer: Vec<Option<Symbol>>,

    /// Next symbol to read from the buffer
    read_index: usize,

    /// Position of the last symbol in the buffer
    last_symbol_index: usize,

    /// Position of the first symbol in the buffer
    first_symbol_index: usize,

    /// True if the target reader has returned None
    end_of_reader: bool,

    /// Number of symbols that have been read from the source
    source_position: usize
}

impl<Symbol: Clone+Sized, SourceReader: SymbolReader<Symbol>> Tape<Symbol, SourceReader> {
    ///
    /// Creates a new tape from a symbol reader
    ///
    pub fn new(source: SourceReader) -> Tape<Symbol, SourceReader> {
        Tape {
            read_from:          source,
            buffer:             vec![None, None, None, None],
            read_index:         0,
            last_symbol_index:  0,
            first_symbol_index: 0,
            end_of_reader:      false,
            source_position:    0
        }
    }

    ///
    /// Resizes the buffer so that it can store at least one more symbol
    ///
    pub fn resize(&mut self) {
        let new_size        = self.buffer.len() * 2;
        let mut new_buffer  = Vec::with_capacity(new_size);

        // Copy all the occupied symbols from the old buffer
        let mut copy_index     = self.first_symbol_index;
        let mut new_read_index = 0;
        while copy_index != self.last_symbol_index {
            new_buffer.push(self.buffer[copy_index].clone());

            copy_index += 1;
            if copy_index >= self.buffer.len() { copy_index = 0; }

            if copy_index == self.read_index { new_read_index = new_buffer.len() }
        }

        // The current length is where the first 'new' symbol will go
        let new_last_symbol_index = new_buffer.len();

        // The rest of the buffer is filled with 'Nones'
        for _ in new_last_symbol_index..new_size {
            new_buffer.push(None);
        }

        // Replace the buffer
        self.buffer             = new_buffer;
        self.first_symbol_index = 0;
        self.last_symbol_index  = new_last_symbol_index;
        self.read_index         = new_read_index;
    }

    ///
    /// Trims the buffer so that it's not possible to rewind past the current read position
    ///
    pub fn cut(&mut self) {
        self.first_symbol_index = self.read_index;
    }

    ///
    /// Returns the number of symbols in the buffer
    ///
    #[inline]
    pub fn buffer_size(&mut self) -> usize {
        if self.first_symbol_index > self.last_symbol_index {
            (self.last_symbol_index + self.buffer.len()) - self.first_symbol_index
        } else {
            self.last_symbol_index - self.first_symbol_index
        }
    }

    ///
    /// Moves backwards by num_symbols
    ///
    pub fn rewind(&mut self, num_symbols: usize) {
        // Do nothing if we're over the maximum length of the buffer
        if num_symbols > self.buffer_size() {
            panic!("Can't rewind beyond the start of the tape");
        }

        // Move backwards num_symbols
        self.source_position -= num_symbols;

        let mut new_read_index = (self.read_index+self.buffer.len()) - num_symbols;
        if new_read_index >= self.buffer.len() { new_read_index -= self.buffer.len(); }

        self.read_index = new_read_index;
    }

    ///
    /// Retrieves the current position in the source stream (number of symbols read since the start)
    ///
    pub fn get_source_position(&self) -> usize {
        self.source_position
    }
}

impl<Symbol: Clone+Sized, Reader: SymbolReader<Symbol>+Sized> SymbolReader<Symbol> for Tape<Symbol, Reader> {
    fn next_symbol(&mut self) -> Option<Symbol> {
        if self.read_index == self.last_symbol_index {
            // If the source reader has ended, there's nothing more to read
            if self.end_of_reader {
                return None;
            }

            // At end of buffer: need to fill it some more
            let maybe_symbol = self.read_from.next_symbol();
            match maybe_symbol {
                None => {
                    // Mark this stream as having finished (we won't read from the source stream any more)
                    self.end_of_reader = true;
                    return None;
                },

                _ => {
                    // Resize the buffer if needed
                    if (self.last_symbol_index+1)%self.buffer.len() == self.first_symbol_index {
                        self.resize();
                    }

                    // Store the next symbol (we'll immediately read it from the buffer later on)
                    self.buffer[self.last_symbol_index] = maybe_symbol;

                    self.last_symbol_index += 1;
                    if self.last_symbol_index >= self.buffer.len() { self.last_symbol_index = 0; }
                }
            }
        }

        // Result is whatever is in the buffer at the read position
        let result = self.buffer[self.read_index].clone();

        self.read_index += 1;
        self.source_position += 1;
        if self.read_index >= self.buffer.len() { self.read_index = 0; }

        result
    }
}

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

    #[test]
    fn can_read_from_tape() {
        let source_vec    = vec![1,2,3,4,5,6];
        let source_stream = source_vec.read_symbols();
        let mut tape      = Tape::new(source_stream);

        assert!(tape.get_source_position() == 0);
        assert!(tape.next_symbol() == Some(1));
        assert!(tape.next_symbol() == Some(2));
        assert!(tape.next_symbol() == Some(3));
        assert!(tape.next_symbol() == Some(4));
        assert!(tape.next_symbol() == Some(5));
        assert!(tape.next_symbol() == Some(6));
        assert!(tape.next_symbol() == None);
        assert!(tape.get_source_position() == 6);
    }

    #[test]
    fn can_rewind_tape() {
        let source_vec    = vec![1,2,3,4,5,6];
        let source_stream = source_vec.read_symbols();
        let mut tape      = Tape::new(source_stream);

        assert!(tape.next_symbol() == Some(1));
        assert!(tape.next_symbol() == Some(2));
        assert!(tape.next_symbol() == Some(3));

        tape.rewind(3);
        assert!(tape.get_source_position() == 0);
        assert!(tape.next_symbol() == Some(1));
        assert!(tape.next_symbol() == Some(2));
        assert!(tape.next_symbol() == Some(3));
        assert!(tape.next_symbol() == Some(4));
        assert!(tape.next_symbol() == Some(5));
        assert!(tape.next_symbol() == Some(6));
        assert!(tape.next_symbol() == None);

        tape.rewind(4);
        assert!(tape.get_source_position() == 2);
        assert!(tape.next_symbol() == Some(3));
        assert!(tape.next_symbol() == Some(4));
        assert!(tape.next_symbol() == Some(5));
        assert!(tape.next_symbol() == Some(6));
        assert!(tape.next_symbol() == None);
    }

    #[test]
    fn can_cut_tape() {
        let source_vec    = vec![1,2,3,4,5,6,7,8,9];
        let source_stream = source_vec.read_symbols();
        let mut tape      = Tape::new(source_stream);

        assert!(tape.next_symbol() == Some(1));
        assert!(tape.next_symbol() == Some(2));
        assert!(tape.next_symbol() == Some(3));
        tape.cut();

        assert!(tape.next_symbol() == Some(4));
        assert!(tape.next_symbol() == Some(5));
        assert!(tape.next_symbol() == Some(6));
        tape.rewind(3);

        assert!(tape.next_symbol() == Some(4));
        assert!(tape.next_symbol() == Some(5));
        assert!(tape.next_symbol() == Some(6));
        assert!(tape.next_symbol() == Some(7));
        assert!(tape.next_symbol() == Some(8));
        assert!(tape.next_symbol() == Some(9));
        assert!(tape.next_symbol() == None);

        tape.rewind(3);
        tape.cut();
        assert!(tape.next_symbol() == Some(7));
        assert!(tape.next_symbol() == Some(8));
        assert!(tape.next_symbol() == Some(9));
        assert!(tape.next_symbol() == None);

        tape.rewind(2);
        assert!(tape.next_symbol() == Some(8));
        assert!(tape.next_symbol() == Some(9));
        assert!(tape.next_symbol() == None);
    }
}
<|endoftext|>


<commit_before>extern crate wlroots_sys;
#[macro_use] extern crate wayland_sys;
extern crate wlroots;

use std::ptr::null_mut;
use std::env;
use std::time::Instant;
use std::os::raw::{c_void, c_int};

struct State {
    /// The color on the screen.
    color: [f32; 3],
    dec: i32,
    /// How long since the last frame was rendered.
    last_frame: Instant,
}

impl State {
    fn new() -> Self {
        State {
            color: [1.0, 0.0, 0.0],
            dec: 0,
            last_frame: Instant::now()
        }
    }
}

fn main() {
    if env::var("DISPLAY").is_ok() {
        panic!("Detected that X is running. Run this in its own virtual terminal.")
    } else if env::var("WAYLAND_DISPLAY").is_ok() {
        panic!("Detected that Wayland is running. Run this in its own virtual terminal")
    }
    let mut session = wlroots::Session::new()
        .expect("Could not start session");
    unsafe {
        // init output (this will eventually be safe).
        wlroots::output::init(&mut session);
    }
    // set loop to break after 3 seconds.
    let mut done = false;
    // TODO This is unsafe, need to make this not pass and require a RefCell
    session.set_timeout(&mut done,
                        |is_done: &mut bool| *is_done = true,
                        3000);
    session.backend.init().expect("Backend could not initalize");
    while done {
        match session.dispatch_event_loop() {
            0 => {}
            err_code => {
                println!("Error: {:?}", err_code);
                break;
            }
        }
    }
    // TODO Ensure that this all cleaned up properly in RAII

}
<commit_msg>Updated example to use 90% safe code so far<commit_after>extern crate wlroots_sys;
#[macro_use] extern crate wayland_sys;
extern crate wlroots;

use std::ptr::null_mut;
use std::env;
use std::time::Instant;
use std::os::raw::{c_void, c_int};
use std::cell::RefCell;
use std::sync::atomic::{AtomicBool, Ordering};

struct State {
    /// The color on the screen.
    color: [f32; 3],
    dec: i32,
    /// How long since the last frame was rendered.
    last_frame: Instant,
}

impl State {
    fn new() -> Self {
        State {
            color: [1.0, 0.0, 0.0],
            dec: 0,
            last_frame: Instant::now()
        }
    }
}

fn main() {
    if env::var("DISPLAY").is_ok() {
        panic!("Detected that X is running. Run this in its own virtual terminal.")
    } else if env::var("WAYLAND_DISPLAY").is_ok() {
        panic!("Detected that Wayland is running. Run this in its own virtual terminal")
    }
    let mut done = AtomicBool::new(false);
    {
        let mut session = wlroots::Session::new()
            .expect("Could not start session");
        unsafe {
            // init output (this will eventually be safe).
            wlroots::output::init(&mut session);
        }
        // set loop to break after 3 seconds.
        // TODO This is unsafe, need to make this not pass and require a RefCell
        session.set_timeout(&done,
                            |done: &AtomicBool|
                            done.store(true, Ordering::Relaxed),
                            3000);
        session.backend.init().expect("Backend could not initalize");
        while done.load(Ordering::Relaxed) {
            match session.dispatch_event_loop() {
                0 => {}
                err_code => {
                    println!("Error: {:?}", err_code);
                    break;
                }
            }
        }
        // TODO Ensure that this all cleaned up properly in RAII
    }

}
<|endoftext|>


<commit_before>// This is used when either vtab or modern-sqlite is on. Different methods are
// used in each feature. Avoid having to track this for each function. We will
// still warn for anything that's not used by either, though.
#![cfg_attr(
    not(all(feature = "vtab", feature = "modern-sqlite")),
    allow(dead_code)
)]
use crate::ffi;
use std::marker::PhantomData;
use std::os::raw::{c_char, c_int};
use std::ptr::NonNull;

/// A string we own that's allocated on the SQLite heap. Automatically calls
/// `sqlite3_free` when dropped, unless `into_raw` (or `into_inner`) is called
/// on it. If constructed from a rust string, `sqlite3_malloc` is used.
///
/// It has identical representation to a nonnull `*mut c_char`, so you can use
/// it transparently as one. It's nonnull, so Option<SqliteMallocString> can be
/// used for nullable ones (it's still just one pointer).
///
/// Most strings shouldn't use this! Only places where the string needs to be
/// freed with `sqlite3_free`. This includes `sqlite3_extended_sql` results,
/// some error message pointers... Note that misuse is extremely dangerous!
///
/// Note that this is *not* a lossless interface. Incoming strings with internal
/// NULs are modified, and outgoing strings which are non-UTF8 are modified.
/// This seems unavoidable -- it tries very hard to not panic.
#[repr(transparent)]
pub(crate) struct SqliteMallocString {
    ptr: NonNull<c_char>,
    _boo: PhantomData<Box<[c_char]>>,
}
// This is owned data for a primitive type, and thus it's safe to implement
// these. That said, nothing needs them, and they make things easier to misuse.

// unsafe impl Send for SqliteMallocString {}
// unsafe impl Sync for SqliteMallocString {}

impl SqliteMallocString {
    /// SAFETY: Caller must be certain that `m` a nul-terminated c string
    /// allocated by sqlite3_malloc, and that SQLite expects us to free it!
    #[inline]
    pub(crate) unsafe fn from_raw_nonnull(ptr: NonNull<c_char>) -> Self {
        Self {
            ptr,
            _boo: PhantomData,
        }
    }

    /// SAFETY: Caller must be certain that `m` a nul-terminated c string
    /// allocated by sqlite3_malloc, and that SQLite expects us to free it!
    #[inline]
    pub(crate) unsafe fn from_raw(ptr: *mut c_char) -> Option<Self> {
        NonNull::new(ptr).map(|p| Self::from_raw_nonnull(p))
    }

    /// Get the pointer behind `self`. After this is called, we no longer manage
    /// it.
    #[inline]
    pub(crate) fn into_inner(self) -> NonNull<c_char> {
        let p = self.ptr;
        std::mem::forget(self);
        p
    }

    /// Get the pointer behind `self`. After this is called, we no longer manage
    /// it.
    #[inline]
    pub(crate) fn into_raw(self) -> *mut c_char {
        self.into_inner().as_ptr()
    }

    /// Borrow the pointer behind `self`. We still manage it when this function
    /// returns. If you want to relinquish ownership, use `into_raw`.
    #[inline]
    pub(crate) fn as_ptr(&self) -> *const c_char {
        self.ptr.as_ptr()
    }

    #[inline]
    pub(crate) fn as_cstr(&self) -> &std::ffi::CStr {
        unsafe { std::ffi::CStr::from_ptr(self.as_ptr()) }
    }

    #[inline]
    pub(crate) fn to_string_lossy(&self) -> std::borrow::Cow<'_, str> {
        self.as_cstr().to_string_lossy()
    }

    /// Convert `s` into a SQLite string.
    ///
    /// This should almost never be done except for cases like error messages or
    /// other strings that SQLite frees.
    ///
    /// If `s` contains internal NULs, we'll replace them with
    /// `NUL_REPLACE_CHAR`.
    ///
    /// Except for debug_asserts which may trigger during testing, this function
    /// never panics. If we hit integer overflow or the allocation fails, we
    /// call `handle_alloc_error` which aborts the program after calling a
    /// global hook.
    ///
    /// This means it's safe to use in extern "C" functions even outside of
    /// catch_unwind.
    pub(crate) fn from_str(s: &str) -> Self {
        use std::convert::TryFrom;
        let s = if s.as_bytes().contains(&0) {
            std::borrow::Cow::Owned(make_nonnull(s))
        } else {
            std::borrow::Cow::Borrowed(s)
        };
        debug_assert!(!s.as_bytes().contains(&0));
        let bytes: &[u8] = s.as_ref().as_bytes();
        let src_ptr: *const c_char = bytes.as_ptr().cast();
        let src_len = bytes.len();
        let maybe_len_plus_1 = s.len().checked_add(1).and_then(|v| c_int::try_from(v).ok());
        unsafe {
            let res_ptr = maybe_len_plus_1
                .and_then(|len_to_alloc| {
                    // `>` because we added 1.
                    debug_assert!(len_to_alloc > 0);
                    debug_assert_eq!((len_to_alloc - 1) as usize, src_len);
                    NonNull::new(ffi::sqlite3_malloc(len_to_alloc) as *mut c_char)
                })
                .unwrap_or_else(|| {
                    use std::alloc::{handle_alloc_error, Layout};
                    // Report via handle_alloc_error so that it can be handled with any
                    // other allocation errors and properly diagnosed.
                    //
                    // This is safe:
                    // - `align` is never 0
                    // - `align` is always a power of 2.
                    // - `size` needs no realignment because it's guaranteed to be
                    //   aligned (everything is aligned to 1)
                    // - `size` is also never zero, although this function doesn't actually require it now.
                    let layout = Layout::from_size_align_unchecked(s.len().saturating_add(1), 1);
                    // Note: This call does not return.
                    handle_alloc_error(layout);
                });
            let buf: *mut i8 = res_ptr.as_ptr();
            src_ptr.copy_to_nonoverlapping(buf, src_len);
            buf.add(src_len).write(0);
            debug_assert_eq!(std::ffi::CStr::from_ptr(res_ptr.as_ptr()).to_bytes(), bytes);
            Self::from_raw_nonnull(res_ptr)
        }
    }
}

const NUL_REPLACE: &str = "␀";

#[cold]
fn make_nonnull(v: &str) -> String {
    v.replace('\0', NUL_REPLACE)
}

impl Drop for SqliteMallocString {
    fn drop(&mut self) {
        unsafe { ffi::sqlite3_free(self.ptr.as_ptr().cast()) };
    }
}

impl std::fmt::Debug for SqliteMallocString {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.to_string_lossy().fmt(f)
    }
}

impl std::fmt::Display for SqliteMallocString {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.to_string_lossy().fmt(f)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn test_from_str() {
        let to_check = [
            ("", ""),
            ("\0", "␀"),
            ("␀", "␀"),
            ("\0bar", "␀bar"),
            ("foo\0bar", "foo␀bar"),
            ("foo\0", "foo␀"),
            ("a\0b\0c\0\0d", "a␀b␀c␀␀d"),
            ("foobar0123", "foobar0123"),
        ];

        for &(input, output) in &to_check {
            let s = SqliteMallocString::from_str(input);
            assert_eq!(s.to_string_lossy(), output);
            assert_eq!(s.as_cstr().to_str().unwrap(), output);
        }
    }

    // This will trigger an asan error if into_raw still freed the ptr.
    #[test]
    fn test_lossy() {
        let p = SqliteMallocString::from_str("abcd").into_raw();
        // Make invalid
        let s = unsafe {
            p.cast::<u8>().write(b'\xff');
            SqliteMallocString::from_raw(p).unwrap()
        };
        assert_eq!(s.to_string_lossy().as_ref(), "\u{FFFD}bcd");
    }

    // This will trigger an asan error if into_raw still freed the ptr.
    #[test]
    fn test_into_raw() {
        let mut v = vec![];
        for i in 0..1000 {
            v.push(SqliteMallocString::from_str(&i.to_string()).into_raw());
            v.push(SqliteMallocString::from_str(&format!("abc {} 😀", i)).into_raw());
        }
        unsafe {
            for (i, s) in v.chunks_mut(2).enumerate() {
                let s0 = std::mem::replace(&mut s[0], std::ptr::null_mut());
                let s1 = std::mem::replace(&mut s[1], std::ptr::null_mut());
                assert_eq!(
                    std::ffi::CStr::from_ptr(s0).to_str().unwrap(),
                    &i.to_string()
                );
                assert_eq!(
                    std::ffi::CStr::from_ptr(s1).to_str().unwrap(),
                    &format!("abc {} 😀", i)
                );
                let _ = SqliteMallocString::from_raw(s0).unwrap();
                let _ = SqliteMallocString::from_raw(s1).unwrap();
            }
        }
    }
}
<commit_msg>Fix SqliteMallocString::from_str on arm32<commit_after>// This is used when either vtab or modern-sqlite is on. Different methods are
// used in each feature. Avoid having to track this for each function. We will
// still warn for anything that's not used by either, though.
#![cfg_attr(
    not(all(feature = "vtab", feature = "modern-sqlite")),
    allow(dead_code)
)]
use crate::ffi;
use std::marker::PhantomData;
use std::os::raw::{c_char, c_int};
use std::ptr::NonNull;

/// A string we own that's allocated on the SQLite heap. Automatically calls
/// `sqlite3_free` when dropped, unless `into_raw` (or `into_inner`) is called
/// on it. If constructed from a rust string, `sqlite3_malloc` is used.
///
/// It has identical representation to a nonnull `*mut c_char`, so you can use
/// it transparently as one. It's nonnull, so Option<SqliteMallocString> can be
/// used for nullable ones (it's still just one pointer).
///
/// Most strings shouldn't use this! Only places where the string needs to be
/// freed with `sqlite3_free`. This includes `sqlite3_extended_sql` results,
/// some error message pointers... Note that misuse is extremely dangerous!
///
/// Note that this is *not* a lossless interface. Incoming strings with internal
/// NULs are modified, and outgoing strings which are non-UTF8 are modified.
/// This seems unavoidable -- it tries very hard to not panic.
#[repr(transparent)]
pub(crate) struct SqliteMallocString {
    ptr: NonNull<c_char>,
    _boo: PhantomData<Box<[c_char]>>,
}
// This is owned data for a primitive type, and thus it's safe to implement
// these. That said, nothing needs them, and they make things easier to misuse.

// unsafe impl Send for SqliteMallocString {}
// unsafe impl Sync for SqliteMallocString {}

impl SqliteMallocString {
    /// SAFETY: Caller must be certain that `m` a nul-terminated c string
    /// allocated by sqlite3_malloc, and that SQLite expects us to free it!
    #[inline]
    pub(crate) unsafe fn from_raw_nonnull(ptr: NonNull<c_char>) -> Self {
        Self {
            ptr,
            _boo: PhantomData,
        }
    }

    /// SAFETY: Caller must be certain that `m` a nul-terminated c string
    /// allocated by sqlite3_malloc, and that SQLite expects us to free it!
    #[inline]
    pub(crate) unsafe fn from_raw(ptr: *mut c_char) -> Option<Self> {
        NonNull::new(ptr).map(|p| Self::from_raw_nonnull(p))
    }

    /// Get the pointer behind `self`. After this is called, we no longer manage
    /// it.
    #[inline]
    pub(crate) fn into_inner(self) -> NonNull<c_char> {
        let p = self.ptr;
        std::mem::forget(self);
        p
    }

    /// Get the pointer behind `self`. After this is called, we no longer manage
    /// it.
    #[inline]
    pub(crate) fn into_raw(self) -> *mut c_char {
        self.into_inner().as_ptr()
    }

    /// Borrow the pointer behind `self`. We still manage it when this function
    /// returns. If you want to relinquish ownership, use `into_raw`.
    #[inline]
    pub(crate) fn as_ptr(&self) -> *const c_char {
        self.ptr.as_ptr()
    }

    #[inline]
    pub(crate) fn as_cstr(&self) -> &std::ffi::CStr {
        unsafe { std::ffi::CStr::from_ptr(self.as_ptr()) }
    }

    #[inline]
    pub(crate) fn to_string_lossy(&self) -> std::borrow::Cow<'_, str> {
        self.as_cstr().to_string_lossy()
    }

    /// Convert `s` into a SQLite string.
    ///
    /// This should almost never be done except for cases like error messages or
    /// other strings that SQLite frees.
    ///
    /// If `s` contains internal NULs, we'll replace them with
    /// `NUL_REPLACE_CHAR`.
    ///
    /// Except for debug_asserts which may trigger during testing, this function
    /// never panics. If we hit integer overflow or the allocation fails, we
    /// call `handle_alloc_error` which aborts the program after calling a
    /// global hook.
    ///
    /// This means it's safe to use in extern "C" functions even outside of
    /// catch_unwind.
    pub(crate) fn from_str(s: &str) -> Self {
        use std::convert::TryFrom;
        let s = if s.as_bytes().contains(&0) {
            std::borrow::Cow::Owned(make_nonnull(s))
        } else {
            std::borrow::Cow::Borrowed(s)
        };
        debug_assert!(!s.as_bytes().contains(&0));
        let bytes: &[u8] = s.as_ref().as_bytes();
        let src_ptr: *const c_char = bytes.as_ptr().cast();
        let src_len = bytes.len();
        let maybe_len_plus_1 = s.len().checked_add(1).and_then(|v| c_int::try_from(v).ok());
        unsafe {
            let res_ptr = maybe_len_plus_1
                .and_then(|len_to_alloc| {
                    // `>` because we added 1.
                    debug_assert!(len_to_alloc > 0);
                    debug_assert_eq!((len_to_alloc - 1) as usize, src_len);
                    NonNull::new(ffi::sqlite3_malloc(len_to_alloc) as *mut c_char)
                })
                .unwrap_or_else(|| {
                    use std::alloc::{handle_alloc_error, Layout};
                    // Report via handle_alloc_error so that it can be handled with any
                    // other allocation errors and properly diagnosed.
                    //
                    // This is safe:
                    // - `align` is never 0
                    // - `align` is always a power of 2.
                    // - `size` needs no realignment because it's guaranteed to be
                    //   aligned (everything is aligned to 1)
                    // - `size` is also never zero, although this function doesn't actually require it now.
                    let layout = Layout::from_size_align_unchecked(s.len().saturating_add(1), 1);
                    // Note: This call does not return.
                    handle_alloc_error(layout);
                });
            let buf: *mut c_char = res_ptr.as_ptr() as *mut c_char;
            src_ptr.copy_to_nonoverlapping(buf, src_len);
            buf.add(src_len).write(0);
            debug_assert_eq!(std::ffi::CStr::from_ptr(res_ptr.as_ptr()).to_bytes(), bytes);
            Self::from_raw_nonnull(res_ptr)
        }
    }
}

const NUL_REPLACE: &str = "␀";

#[cold]
fn make_nonnull(v: &str) -> String {
    v.replace('\0', NUL_REPLACE)
}

impl Drop for SqliteMallocString {
    fn drop(&mut self) {
        unsafe { ffi::sqlite3_free(self.ptr.as_ptr().cast()) };
    }
}

impl std::fmt::Debug for SqliteMallocString {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.to_string_lossy().fmt(f)
    }
}

impl std::fmt::Display for SqliteMallocString {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.to_string_lossy().fmt(f)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn test_from_str() {
        let to_check = [
            ("", ""),
            ("\0", "␀"),
            ("␀", "␀"),
            ("\0bar", "␀bar"),
            ("foo\0bar", "foo␀bar"),
            ("foo\0", "foo␀"),
            ("a\0b\0c\0\0d", "a␀b␀c␀␀d"),
            ("foobar0123", "foobar0123"),
        ];

        for &(input, output) in &to_check {
            let s = SqliteMallocString::from_str(input);
            assert_eq!(s.to_string_lossy(), output);
            assert_eq!(s.as_cstr().to_str().unwrap(), output);
        }
    }

    // This will trigger an asan error if into_raw still freed the ptr.
    #[test]
    fn test_lossy() {
        let p = SqliteMallocString::from_str("abcd").into_raw();
        // Make invalid
        let s = unsafe {
            p.cast::<u8>().write(b'\xff');
            SqliteMallocString::from_raw(p).unwrap()
        };
        assert_eq!(s.to_string_lossy().as_ref(), "\u{FFFD}bcd");
    }

    // This will trigger an asan error if into_raw still freed the ptr.
    #[test]
    fn test_into_raw() {
        let mut v = vec![];
        for i in 0..1000 {
            v.push(SqliteMallocString::from_str(&i.to_string()).into_raw());
            v.push(SqliteMallocString::from_str(&format!("abc {} 😀", i)).into_raw());
        }
        unsafe {
            for (i, s) in v.chunks_mut(2).enumerate() {
                let s0 = std::mem::replace(&mut s[0], std::ptr::null_mut());
                let s1 = std::mem::replace(&mut s[1], std::ptr::null_mut());
                assert_eq!(
                    std::ffi::CStr::from_ptr(s0).to_str().unwrap(),
                    &i.to_string()
                );
                assert_eq!(
                    std::ffi::CStr::from_ptr(s1).to_str().unwrap(),
                    &format!("abc {} 😀", i)
                );
                let _ = SqliteMallocString::from_raw(s0).unwrap();
                let _ = SqliteMallocString::from_raw(s1).unwrap();
            }
        }
    }
}
<|endoftext|>