<commit_before>use std::future::Future;
use std::pin::Pin;
use std::task::Poll;

use bytes::Bytes;
use futures::future;
use futures::stream;
use futures::stream::Stream;
use futures::stream::StreamExt;
use futures::task::Context;
use futures::TryFutureExt;
use futures::TryStreamExt;

use crate::data_or_headers::DataOrHeaders;
use crate::data_or_headers_with_flag::DataOrHeadersWithFlag;
use crate::data_or_headers_with_flag::DataOrHeadersWithFlagStream;
use crate::message::SimpleHttpMessage;
use crate::solicit::header::Headers;
use crate::solicit_async::*;
use crate::stream_after_headers::HttpStreamAfterHeaders;

/// Convenient wrapper around async HTTP response future/stream
pub struct ClientResponseFuture(pub HttpFutureSend<(Headers, HttpStreamAfterHeaders)>);

impl ClientResponseFuture {
    // constructors

    pub fn new<F>(future: F) -> ClientResponseFuture
    where
        F: Future<Output = crate::Result<(Headers, HttpStreamAfterHeaders)>> + Send + 'static,
    {
        ClientResponseFuture(Box::pin(future))
    }

    pub fn headers_and_stream(
        headers: Headers,
        stream: HttpStreamAfterHeaders,
    ) -> ClientResponseFuture {
        ClientResponseFuture::new(future::ok((headers, stream)))
    }

    pub fn headers_and_bytes_stream<S>(headers: Headers, content: S) -> ClientResponseFuture
    where
        S: Stream<Item = crate::Result<Bytes>> + Send + 'static,
    {
        ClientResponseFuture::headers_and_stream(headers, HttpStreamAfterHeaders::bytes(content))
    }

    /// Create a response with only headers
    pub fn headers(headers: Headers) -> ClientResponseFuture {
        ClientResponseFuture::headers_and_bytes_stream(headers, stream::empty())
    }

    /// Create a response with headers and response body
    pub fn headers_and_bytes<B: Into<Bytes>>(header: Headers, content: B) -> ClientResponseFuture {
        ClientResponseFuture::headers_and_bytes_stream(
            header,
            stream::once(future::ok(content.into())),
        )
    }

    pub fn message(message: SimpleHttpMessage) -> ClientResponseFuture {
        ClientResponseFuture::headers_and_bytes(message.headers, message.body)
    }

    pub fn found_200_plain_text(body: &str) -> ClientResponseFuture {
        ClientResponseFuture::message(SimpleHttpMessage::found_200_plain_text(body))
    }

    pub fn not_found_404() -> ClientResponseFuture {
        ClientResponseFuture::headers(Headers::not_found_404())
    }

    pub fn redirect_302(location: &str) -> ClientResponseFuture {
        let mut headers = Headers::new_status(302);
        headers.add("location", location);
        ClientResponseFuture::headers(headers)
    }

    pub fn from_stream<S>(mut stream: S) -> ClientResponseFuture
    where
        S: Stream<Item = crate::Result<DataOrHeadersWithFlag>> + Unpin + Send + 'static,
    {
        ClientResponseFuture::new(async move {
            // Check that first frame is HEADERS
            let (first, rem) = match stream.try_next().await? {
                Some(part) => match part.content {
                    DataOrHeaders::Headers(headers) => {
                        (headers, HttpStreamAfterHeaders::from_parts(stream))
                    }
                    DataOrHeaders::Data(..) => {
                        return Err(crate::Error::InvalidFrame("data before headers".to_owned()))
                    }
                },
                None => {
                    return Err(crate::Error::InvalidFrame(
                        "empty response, expecting headers".to_owned(),
                    ))
                }
            };
            Ok((first, rem))
        })
    }

    pub fn err(err: crate::Error) -> ClientResponseFuture {
        ClientResponseFuture::new(future::err(err))
    }

    // getters

    pub fn into_stream_flag(self) -> HttpFutureStreamSend<DataOrHeadersWithFlag> {
        Box::pin(
            self.0
                .map_ok(|(headers, rem)| {
                    // NOTE: flag may be wrong for first item
                    let header = stream::once(future::ok(
                        DataOrHeadersWithFlag::intermediate_headers(headers),
                    ));
                    let rem = rem.into_flag_stream();
                    header.chain(rem)
                })
                .try_flatten_stream(),
        )
    }

    pub fn into_stream(self) -> HttpFutureStreamSend<DataOrHeaders> {
        Box::pin(TryStreamExt::map_ok(self.into_stream_flag(), |c| c.content))
    }

    pub fn into_part_stream(self) -> DataOrHeadersWithFlagStream {
        DataOrHeadersWithFlagStream::new(self.into_stream_flag())
    }

    pub fn collect(self) -> HttpFutureSend<SimpleHttpMessage> {
        Box::pin(
            self.into_stream()
                .try_fold(SimpleHttpMessage::new(), |mut c, p| {
                    c.add(p);
                    future::ok::<_, crate::Error>(c)
                }),
        )
    }
}

impl Future for ClientResponseFuture {
    type Output = crate::Result<(Headers, HttpStreamAfterHeaders)>;

    fn poll(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<crate::Result<(Headers, HttpStreamAfterHeaders)>> {
        Pin::new(&mut self.0).poll(cx)
    }
}
<commit_msg>Remove some dead code<commit_after>use std::future::Future;
use std::pin::Pin;
use std::task::Poll;

use futures::future;
use futures::stream;
use futures::stream::Stream;
use futures::stream::StreamExt;
use futures::task::Context;
use futures::TryFutureExt;
use futures::TryStreamExt;

use crate::data_or_headers::DataOrHeaders;
use crate::data_or_headers_with_flag::DataOrHeadersWithFlag;
use crate::data_or_headers_with_flag::DataOrHeadersWithFlagStream;
use crate::message::SimpleHttpMessage;
use crate::solicit::header::Headers;
use crate::solicit_async::*;
use crate::stream_after_headers::HttpStreamAfterHeaders;

/// Convenient wrapper around async HTTP response future/stream
pub struct ClientResponseFuture(pub HttpFutureSend<(Headers, HttpStreamAfterHeaders)>);

impl ClientResponseFuture {
    // constructors

    pub fn new<F>(future: F) -> ClientResponseFuture
    where
        F: Future<Output = crate::Result<(Headers, HttpStreamAfterHeaders)>> + Send + 'static,
    {
        ClientResponseFuture(Box::pin(future))
    }

    pub fn from_stream<S>(mut stream: S) -> ClientResponseFuture
    where
        S: Stream<Item = crate::Result<DataOrHeadersWithFlag>> + Unpin + Send + 'static,
    {
        ClientResponseFuture::new(async move {
            // Check that first frame is HEADERS
            let (first, rem) = match stream.try_next().await? {
                Some(part) => match part.content {
                    DataOrHeaders::Headers(headers) => {
                        (headers, HttpStreamAfterHeaders::from_parts(stream))
                    }
                    DataOrHeaders::Data(..) => {
                        return Err(crate::Error::InvalidFrame("data before headers".to_owned()))
                    }
                },
                None => {
                    return Err(crate::Error::InvalidFrame(
                        "empty response, expecting headers".to_owned(),
                    ))
                }
            };
            Ok((first, rem))
        })
    }

    // getters

    pub fn into_stream_flag(self) -> HttpFutureStreamSend<DataOrHeadersWithFlag> {
        Box::pin(
            self.0
                .map_ok(|(headers, rem)| {
                    // NOTE: flag may be wrong for first item
                    let header = stream::once(future::ok(
                        DataOrHeadersWithFlag::intermediate_headers(headers),
                    ));
                    let rem = rem.into_flag_stream();
                    header.chain(rem)
                })
                .try_flatten_stream(),
        )
    }

    pub fn into_stream(self) -> HttpFutureStreamSend<DataOrHeaders> {
        Box::pin(TryStreamExt::map_ok(self.into_stream_flag(), |c| c.content))
    }

    pub fn into_part_stream(self) -> DataOrHeadersWithFlagStream {
        DataOrHeadersWithFlagStream::new(self.into_stream_flag())
    }

    pub fn collect(self) -> HttpFutureSend<SimpleHttpMessage> {
        Box::pin(
            self.into_stream()
                .try_fold(SimpleHttpMessage::new(), |mut c, p| {
                    c.add(p);
                    future::ok::<_, crate::Error>(c)
                }),
        )
    }
}

impl Future for ClientResponseFuture {
    type Output = crate::Result<(Headers, HttpStreamAfterHeaders)>;

    fn poll(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<crate::Result<(Headers, HttpStreamAfterHeaders)>> {
        Pin::new(&mut self.0).poll(cx)
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
//
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the THIRD-PARTY file.

use super::super::{ActivateError, ActivateResult, Queue, VirtioDevice};
use super::handle::*;
use super::*;

use memory_model::GuestMemory;
use sys_util::EventFd;
use vhost_backend::Vhost;
use vhost_backend::Vsock as VhostVsockFd;
use vhost_gen::vhost::*;
use virtio_gen::virtio_config::*;
use virtio_gen::virtio_ring::*;

use byteorder::{ByteOrder, LittleEndian};
use epoll;
use std::sync::atomic::AtomicUsize;
use std::sync::Arc;

const QUEUE_SIZE: u16 = 256;
const NUM_QUEUES: usize = 3;
const QUEUE_SIZES: &'static [u16] = &[QUEUE_SIZE; NUM_QUEUES];

impl std::convert::From<super::Error> for ActivateError {
    fn from(error: super::Error) -> Self {
        ActivateError::BadVhostActivate(error)
    }
}

pub struct Vsock {
    vsock_fd: Option<VhostVsockFd>,
    cid: u64,
    avail_features: u64,
    acked_features: u64,
    config_space: Vec<u8>,
    epoll_config: VhostEpollConfig,
    interrupt: Option<EventFd>,
}

impl Vsock {
    /// Create a new virtio-vsock device with the given VM cid.
    pub fn new(cid: u64, mem: &GuestMemory, epoll_config: VhostEpollConfig) -> Result<Vsock> {
        let fd = VhostVsockFd::new(mem).map_err(Error::VhostOpen)?;
        let avail_features = fd.get_features().map_err(Error::VhostGetFeatures)?;

        Ok(Vsock {
            vsock_fd: Some(fd),
            cid,
            avail_features,
            acked_features: 0,
            config_space: Vec::new(),
            epoll_config,
            interrupt: Some(EventFd::new().map_err(Error::VhostIrqCreate)?),
        })
    }
}

impl VirtioDevice for Vsock {
    fn device_type(&self) -> u32 {
        TYPE_VSOCK
    }

    fn queue_max_sizes(&self) -> &[u16] {
        QUEUE_SIZES
    }

    fn features(&self, page: u32) -> u32 {
        match page {
            // Get the lower 32-bits of the features bitfield.
            0 => self.avail_features as u32,
            // Get the upper 32-bits of the features bitfield.
            1 => (self.avail_features >> 32) as u32,
            _ => {
                warn!(
                    "vsock: virtio-vsock got request for features page: {}",
                    page
                );
                0u32
            }
        }
    }

    fn ack_features(&mut self, page: u32, value: u32) {
        let mut v = match page {
            0 => value as u64,
            1 => (value as u64) << 32,
            _ => {
                warn!(
                    "vsock: virtio-vsock device cannot ack unknown feature page: {}",
                    page
                );
                0u64
            }
        };

        // Check if the guest is ACK'ing a feature that we didn't claim to have.
        let unrequested_features = v & !self.avail_features;
        if unrequested_features != 0 {
            warn!("vsock: virtio-vsock got unknown feature ack: {:x}", v);

            // Don't count these features as acked.
            v &= !unrequested_features;
        }
        self.acked_features |= v;
    }

    fn read_config(&self, offset: u64, data: &mut [u8]) {
        match offset {
            0 if data.len() == 8 => LittleEndian::write_u64(data, self.cid),
            0 if data.len() == 4 => LittleEndian::write_u32(data, (self.cid & 0xffffffff) as u32),
            4 if data.len() == 4 => {
                LittleEndian::write_u32(data, ((self.cid >> 32) & 0xffffffff) as u32)
            }
            _ => warn!(
                "vsock: virtio-vsock received invalid read request of {} bytes at offset {}",
                data.len(),
                offset
            ),
        }
    }

    fn write_config(&mut self, offset: u64, data: &[u8]) {
        let data_len = data.len() as u64;
        let config_len = self.config_space.len() as u64;
        if offset + data_len > config_len {
            error!("Failed to write config space");
            return;
        }
        let (_, right) = self.config_space.split_at_mut(offset as usize);
        right.copy_from_slice(&data[..]);
    }

    fn activate(
        &mut self,
        _: GuestMemory,
        interrupt_evt: EventFd,
        interrupt_status: Arc<AtomicUsize>,
        queues: Vec<Queue>,
        queue_evts: Vec<EventFd>,
    ) -> ActivateResult {
        if queues.len() != NUM_QUEUES || queue_evts.len() != NUM_QUEUES {
            error!(
                "Cannot perform activate. Expected {} queue(s), got {}",
                NUM_QUEUES,
                queues.len()
            );
            return Err(ActivateError::BadActivate);
        }

        if let Some(vsock_fd) = self.vsock_fd.take() {
            if let Some(interrupt) = self.interrupt.take() {
                let cid = self.cid;

                // The third vq is an event-only vq that is not handled by the vhost
                // subsystem (but still needs to exist).  Split it off here.
                let vhost_queues = queues[..2].to_vec();

                // Preliminary setup for vhost net.
                vsock_fd.set_owner().map_err(Error::VhostSetOwner)?;

                vsock_fd
                    .set_features(self.acked_features)
                    .map_err(Error::VhostSetFeatures)?;

                vsock_fd.set_mem_table().map_err(Error::VhostSetMemTable)?;

                for (queue_index, ref queue) in vhost_queues.iter().enumerate() {
                    vsock_fd
                        .set_vring_num(queue_index, queue.get_max_size())
                        .map_err(Error::VhostSetVringNum)?;

                    vsock_fd
                        .set_vring_addr(
                            QUEUE_SIZES[queue_index],
                            queue.actual_size(),
                            queue_index,
                            0,
                            queue.desc_table,
                            queue.used_ring,
                            queue.avail_ring,
                            None,
                        )
                        .map_err(Error::VhostSetVringAddr)?;
                    vsock_fd
                        .set_vring_base(queue_index, 0)
                        .map_err(Error::VhostSetVringBase)?;
                    vsock_fd
                        .set_vring_call(queue_index, &interrupt)
                        .map_err(Error::VhostSetVringCall)?;
                    vsock_fd
                        .set_vring_kick(queue_index, &queue_evts[queue_index])
                        .map_err(Error::VhostSetVringKick)?;
                }

                let handler =
                    VhostEpollHandler::new(vsock_fd, interrupt_status, interrupt_evt, interrupt);

                // vsock specific ioctl setup for running device.
                handler
                    .get_device()
                    .set_guest_cid(cid)
                    .map_err(Error::VhostVsockSetCid)?;
                handler
                    .get_device()
                    .start()
                    .map_err(Error::VhostVsockStart)?;

                let queue_evt_raw_fd = handler.get_queue_evt();
                //channel should be open and working
                self.epoll_config
                    .get_sender()
                    .send(Box::new(handler))
                    .unwrap();

                epoll::ctl(
                    self.epoll_config.get_raw_epoll_fd(),
                    epoll::ControlOptions::EPOLL_CTL_ADD,
                    queue_evt_raw_fd,
                    epoll::Event::new(
                        epoll::Events::EPOLLIN,
                        self.epoll_config.get_queue_evt_token(),
                    ),
                )
                .map_err(ActivateError::EpollCtl)?;

                return Ok(());
            }
        }
        Err(ActivateError::BadActivate)
    }
}
<commit_msg>vsock: get rid of compilation warnings<commit_after>// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
//
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the THIRD-PARTY file.

use super::super::{ActivateError, ActivateResult, Queue, VirtioDevice};
use super::handle::*;
use super::*;

use memory_model::GuestMemory;
use sys_util::EventFd;
use vhost_backend::Vhost;
use vhost_backend::Vsock as VhostVsockFd;

use byteorder::{ByteOrder, LittleEndian};
use epoll;
use std::sync::atomic::AtomicUsize;
use std::sync::Arc;

const QUEUE_SIZE: u16 = 256;
const NUM_QUEUES: usize = 3;
const QUEUE_SIZES: &'static [u16] = &[QUEUE_SIZE; NUM_QUEUES];

impl std::convert::From<super::Error> for ActivateError {
    fn from(error: super::Error) -> Self {
        ActivateError::BadVhostActivate(error)
    }
}

pub struct Vsock {
    vsock_fd: Option<VhostVsockFd>,
    cid: u64,
    avail_features: u64,
    acked_features: u64,
    config_space: Vec<u8>,
    epoll_config: VhostEpollConfig,
    interrupt: Option<EventFd>,
}

impl Vsock {
    /// Create a new virtio-vsock device with the given VM cid.
    pub fn new(cid: u64, mem: &GuestMemory, epoll_config: VhostEpollConfig) -> Result<Vsock> {
        let fd = VhostVsockFd::new(mem).map_err(Error::VhostOpen)?;
        let avail_features = fd.get_features().map_err(Error::VhostGetFeatures)?;

        Ok(Vsock {
            vsock_fd: Some(fd),
            cid,
            avail_features,
            acked_features: 0,
            config_space: Vec::new(),
            epoll_config,
            interrupt: Some(EventFd::new().map_err(Error::VhostIrqCreate)?),
        })
    }
}

impl VirtioDevice for Vsock {
    fn device_type(&self) -> u32 {
        TYPE_VSOCK
    }

    fn queue_max_sizes(&self) -> &[u16] {
        QUEUE_SIZES
    }

    fn features(&self, page: u32) -> u32 {
        match page {
            // Get the lower 32-bits of the features bitfield.
            0 => self.avail_features as u32,
            // Get the upper 32-bits of the features bitfield.
            1 => (self.avail_features >> 32) as u32,
            _ => {
                warn!(
                    "vsock: virtio-vsock got request for features page: {}",
                    page
                );
                0u32
            }
        }
    }

    fn ack_features(&mut self, page: u32, value: u32) {
        let mut v = match page {
            0 => value as u64,
            1 => (value as u64) << 32,
            _ => {
                warn!(
                    "vsock: virtio-vsock device cannot ack unknown feature page: {}",
                    page
                );
                0u64
            }
        };

        // Check if the guest is ACK'ing a feature that we didn't claim to have.
        let unrequested_features = v & !self.avail_features;
        if unrequested_features != 0 {
            warn!("vsock: virtio-vsock got unknown feature ack: {:x}", v);

            // Don't count these features as acked.
            v &= !unrequested_features;
        }
        self.acked_features |= v;
    }

    fn read_config(&self, offset: u64, data: &mut [u8]) {
        match offset {
            0 if data.len() == 8 => LittleEndian::write_u64(data, self.cid),
            0 if data.len() == 4 => LittleEndian::write_u32(data, (self.cid & 0xffffffff) as u32),
            4 if data.len() == 4 => {
                LittleEndian::write_u32(data, ((self.cid >> 32) & 0xffffffff) as u32)
            }
            _ => warn!(
                "vsock: virtio-vsock received invalid read request of {} bytes at offset {}",
                data.len(),
                offset
            ),
        }
    }

    fn write_config(&mut self, offset: u64, data: &[u8]) {
        let data_len = data.len() as u64;
        let config_len = self.config_space.len() as u64;
        if offset + data_len > config_len {
            error!("Failed to write config space");
            return;
        }
        let (_, right) = self.config_space.split_at_mut(offset as usize);
        right.copy_from_slice(&data[..]);
    }

    fn activate(
        &mut self,
        _: GuestMemory,
        interrupt_evt: EventFd,
        interrupt_status: Arc<AtomicUsize>,
        queues: Vec<Queue>,
        queue_evts: Vec<EventFd>,
    ) -> ActivateResult {
        if queues.len() != NUM_QUEUES || queue_evts.len() != NUM_QUEUES {
            error!(
                "Cannot perform activate. Expected {} queue(s), got {}",
                NUM_QUEUES,
                queues.len()
            );
            return Err(ActivateError::BadActivate);
        }

        if let Some(vsock_fd) = self.vsock_fd.take() {
            if let Some(interrupt) = self.interrupt.take() {
                let cid = self.cid;

                // The third vq is an event-only vq that is not handled by the vhost
                // subsystem (but still needs to exist).  Split it off here.
                let vhost_queues = queues[..2].to_vec();

                // Preliminary setup for vhost net.
                vsock_fd.set_owner().map_err(Error::VhostSetOwner)?;

                vsock_fd
                    .set_features(self.acked_features)
                    .map_err(Error::VhostSetFeatures)?;

                vsock_fd.set_mem_table().map_err(Error::VhostSetMemTable)?;

                for (queue_index, ref queue) in vhost_queues.iter().enumerate() {
                    vsock_fd
                        .set_vring_num(queue_index, queue.get_max_size())
                        .map_err(Error::VhostSetVringNum)?;

                    vsock_fd
                        .set_vring_addr(
                            QUEUE_SIZES[queue_index],
                            queue.actual_size(),
                            queue_index,
                            0,
                            queue.desc_table,
                            queue.used_ring,
                            queue.avail_ring,
                            None,
                        )
                        .map_err(Error::VhostSetVringAddr)?;
                    vsock_fd
                        .set_vring_base(queue_index, 0)
                        .map_err(Error::VhostSetVringBase)?;
                    vsock_fd
                        .set_vring_call(queue_index, &interrupt)
                        .map_err(Error::VhostSetVringCall)?;
                    vsock_fd
                        .set_vring_kick(queue_index, &queue_evts[queue_index])
                        .map_err(Error::VhostSetVringKick)?;
                }

                let handler =
                    VhostEpollHandler::new(vsock_fd, interrupt_status, interrupt_evt, interrupt);

                // vsock specific ioctl setup for running device.
                handler
                    .get_device()
                    .set_guest_cid(cid)
                    .map_err(Error::VhostVsockSetCid)?;
                handler
                    .get_device()
                    .start()
                    .map_err(Error::VhostVsockStart)?;

                let queue_evt_raw_fd = handler.get_queue_evt();
                //channel should be open and working
                self.epoll_config
                    .get_sender()
                    .send(Box::new(handler))
                    .unwrap();

                epoll::ctl(
                    self.epoll_config.get_raw_epoll_fd(),
                    epoll::ControlOptions::EPOLL_CTL_ADD,
                    queue_evt_raw_fd,
                    epoll::Event::new(
                        epoll::Events::EPOLLIN,
                        self.epoll_config.get_queue_evt_token(),
                    ),
                )
                .map_err(ActivateError::EpollCtl)?;

                return Ok(());
            }
        }
        Err(ActivateError::BadActivate)
    }
}
<|endoftext|>


<commit_before>// pest. The Elegant Parser
// Copyright (c) 2018 Dragoș Tiselice
//
// 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. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use ast::*;

pub fn list(rule: Rule) -> Rule {
    match rule {
        Rule { name, ty, expr } => Rule {
            name,
            ty,
            expr: expr.map_bottom_up(|expr| {
                // TODO: Use box syntax when it gets stabilized.
                match expr {
                    Expr::Seq(l, r) => match *l {
                        Expr::Rep(l) => match *l {
                            Expr::Seq(l1, l2) => {
                                // Converts `(rule ~ rest)* ~ rule` to `rule ~ (rest ~ rule)*`,
                                // avoiding matching the last `rule` twice.
                                if l1 == r {
                                    Expr::Seq(l1, Box::new(Expr::Rep(Box::new(Expr::Seq(l2, r)))))
                                } else {
                                    Expr::Seq(Box::new(Expr::Rep(Box::new(Expr::Seq(l1, l2)))), r)
                                }
                            }
                            expr => Expr::Seq(Box::new(Expr::Rep(Box::new(expr))), r),
                        },
                        expr => Expr::Seq(Box::new(expr), r),
                    },
                    expr => expr,
                }
            }),
        },
    }
}
<commit_msg>Added workaround for pre-NLL compiler bug<commit_after>// pest. The Elegant Parser
// Copyright (c) 2018 Dragoș Tiselice
//
// 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. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use ast::*;

pub fn list(rule: Rule) -> Rule {
    match rule {
        Rule { name, ty, expr } => Rule {
            name,
            ty,
            expr: expr.map_bottom_up(|expr| {
                // TODO: Use box syntax when it gets stabilized.
                match expr {
                    Expr::Seq(l, r) => match *l {
                        Expr::Rep(l) => {
                            let l = *l;
                            match l {
                                Expr::Seq(l1, l2) => {
                                    // Converts `(rule ~ rest)* ~ rule` to `rule ~ (rest ~ rule)*`,
                                    // avoiding matching the last `rule` twice.
                                    if l1 == r {
                                        Expr::Seq(
                                            l1,
                                            Box::new(Expr::Rep(Box::new(Expr::Seq(l2, r)))),
                                        )
                                    } else {
                                        Expr::Seq(
                                            Box::new(Expr::Rep(Box::new(Expr::Seq(l1, l2)))),
                                            r,
                                        )
                                    }
                                }
                                expr => Expr::Seq(Box::new(Expr::Rep(Box::new(expr))), r),
                            }
                        }
                        expr => Expr::Seq(Box::new(expr), r),
                    },
                    expr => expr,
                }
            }),
        },
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;

use traits::Nhood;
use traits::Coord;

pub struct VonNeumannNhood<C: Coord> {
    phantom: PhantomData<C>,
}

impl<C: Coord> VonNeumannNhood<C> {
    pub fn new() -> Self { VonNeumannNhood { phantom: PhantomData } }
}

impl<C: Coord> Nhood for VonNeumannNhood<C> {
    type Coord = C;

    // - | 0 | -
    // 1 | x | 2
    // - | 3 | -
    fn neighbors(&self, coord: &Self::Coord) -> Vec<Self::Coord> {

        let x = coord.x();
        let y = coord.y();

        let neighbors_coords = vec![
                                      C::from_2d(x, y - 1),
            C::from_2d(x - 1, y),     /* x */               C::from_2d(x + 1, y),
                                      C::from_2d(x, y + 1),
        ];

        neighbors_coords
    }

    fn neighbors_count(&self) -> usize { 4 }
}

#[cfg(test)]
mod tests {

    use traits::Nhood;
    use super::VonNeumannNhood;

    #[test]
    fn test_von_neumann_nhood() {
        let nhood = VonNeumannNhood::new();

        let center = (1, 1);

        let neighbors = nhood.neighbors(&center);
        assert_eq!(neighbors.len(), nhood.neighbors_count());

        assert_eq!(neighbors[0], (1, 0));
        assert_eq!(neighbors[1], (0, 1));
        assert_eq!(neighbors[2], (2, 1));
        assert_eq!(neighbors[3], (1, 2));
    }
}
<commit_msg>Note about VonNeumann neighborhood.<commit_after>use std::marker::PhantomData;

use traits::Nhood;
use traits::Coord;

/// Implements Von Neumann neighborhood.
pub struct VonNeumannNhood<C: Coord> {
    phantom: PhantomData<C>,
}

impl<C: Coord> VonNeumannNhood<C> {
    /// Just constructor.
    pub fn new() -> Self { VonNeumannNhood { phantom: PhantomData } }
}

impl<C: Coord> Nhood for VonNeumannNhood<C> {
    type Coord = C;

    // - | 0 | -
    // 1 | x | 2
    // - | 3 | -
    fn neighbors(&self, coord: &Self::Coord) -> Vec<Self::Coord> {

        let x = coord.x();
        let y = coord.y();

        let neighbors_coords = vec![
                                      C::from_2d(x, y - 1),
            C::from_2d(x - 1, y),     /* x */               C::from_2d(x + 1, y),
                                      C::from_2d(x, y + 1),
        ];

        neighbors_coords
    }

    fn neighbors_count(&self) -> usize { 4 }
}

#[cfg(test)]
mod tests {

    use traits::Nhood;
    use super::VonNeumannNhood;

    #[test]
    fn test_von_neumann_nhood() {
        let nhood = VonNeumannNhood::new();

        let center = (1, 1);

        let neighbors = nhood.neighbors(&center);
        assert_eq!(neighbors.len(), nhood.neighbors_count());

        assert_eq!(neighbors[0], (1, 0));
        assert_eq!(neighbors[1], (0, 1));
        assert_eq!(neighbors[2], (2, 1));
        assert_eq!(neighbors[3], (1, 2));
    }
}
<|endoftext|>


<commit_before>/* diosix capsule-provided service management

 * (c) Chris Williams, 2019-2020.
 *
 * See LICENSE for usage and copying.
 */

use super::lock::Mutex;
use hashbrown::hash_map::{HashMap, Entry};
use alloc::collections::vec_deque::VecDeque;
use super::message;
use super::error::Cause;
use super::capsule::{self, CapsuleID};

pub type ServiceID = usize;

/* todo: a fixed list of known system services,
such as video, sound, serial, network, etc
that privileged / trusted capsules can register.
then other capsules can message those services
to access those underlying resources. */

/* maintain a table of registered services */
lazy_static!
{
    static ref SERVICES: Mutex<HashMap<ServiceID, Service>> = Mutex::new(HashMap::new());
}

/* describe an individual service */
struct Service
{
    capsuleid: CapsuleID,       /* capsule that's registered this service */
    msgs: VecDeque<message::Message>  /* queue of messages to deliver to service */
}

impl Service
{
    pub fn queue(&mut self, msg: message::Message)
    {
        self.msgs.push_front(msg);
    }
}

/* register a service for a capsule. this will fail if the service is
   already registered or if the capsule has no right to run the service
   or if the capsule doesn't exist.
    => sid = ID of service to register
       cid = ID of capsule to handle this service
    <= return Ok for success, or a failure code */
pub fn register(sid: ServiceID, cid: CapsuleID) -> Result<(), Cause>
{
    match capsule::is_service_allowed(cid, sid)
    {
        Some(flag) => if flag == false
        {
            return Err(Cause::ServiceNotAllowed);
        },
        None => return Err(Cause::CapsuleBadID)
    };

    let service = Service
    {
        capsuleid: cid,
        msgs: VecDeque::new()
    };

    /* ensure we do not double register a service */
    if let Entry::Vacant(v) = SERVICES.lock().entry(sid)
    {
        v.insert(service);
        return Ok(());
    }
    else
    {
        return Err(Cause::ServiceAlreadyRegistered)
    }
}

/* deregister a service so that its capsule is no longer responsible for it
   => sid = service to deregister
   <= Ok for success, or an error code for failure */
pub fn deregister(sid: ServiceID) -> Result<(), Cause>
{
    match SERVICES.lock().remove(&sid)
    {
        None => Err(Cause::ServiceNotFound),
        _ => Ok(())
    }
}

/* send the given message msg to a registered service */
pub fn send(msg: message::Message) -> Result<(), Cause>
{
    let sid = match msg.get_receiver()
    {
        message::Recipient::Service(sid) => sid,
        _ => return Err(Cause::MessageBadType)
    };

    if let Some(service) = SERVICES.lock().get_mut(&sid)
    {
        service.queue(msg);
        Ok(())
    }
    else
    {
        return Err(Cause::ServiceNotAllowed)
    }
}<commit_msg>Use named mutex<commit_after>/* diosix capsule-provided service management

 * (c) Chris Williams, 2019-2020.
 *
 * See LICENSE for usage and copying.
 */

use super::lock::Mutex;
use hashbrown::hash_map::{HashMap, Entry};
use alloc::collections::vec_deque::VecDeque;
use super::message;
use super::error::Cause;
use super::capsule::{self, CapsuleID};

pub type ServiceID = usize;

/* todo: a fixed list of known system services,
such as video, sound, serial, network, etc
that privileged / trusted capsules can register.
then other capsules can message those services
to access those underlying resources. */

/* maintain a table of registered services */
lazy_static!
{
    static ref SERVICES: Mutex<HashMap<ServiceID, Service>> = Mutex::new("system service table", HashMap::new());
}

/* describe an individual service */
struct Service
{
    capsuleid: CapsuleID,       /* capsule that's registered this service */
    msgs: VecDeque<message::Message>  /* queue of messages to deliver to service */
}

impl Service
{
    pub fn queue(&mut self, msg: message::Message)
    {
        self.msgs.push_front(msg);
    }
}

/* register a service for a capsule. this will fail if the service is
   already registered or if the capsule has no right to run the service
   or if the capsule doesn't exist.
    => sid = ID of service to register
       cid = ID of capsule to handle this service
    <= return Ok for success, or a failure code */
pub fn register(sid: ServiceID, cid: CapsuleID) -> Result<(), Cause>
{
    match capsule::is_service_allowed(cid, sid)
    {
        Some(flag) => if flag == false
        {
            return Err(Cause::ServiceNotAllowed);
        },
        None => return Err(Cause::CapsuleBadID)
    };

    let service = Service
    {
        capsuleid: cid,
        msgs: VecDeque::new()
    };

    /* ensure we do not double register a service */
    if let Entry::Vacant(v) = SERVICES.lock().entry(sid)
    {
        v.insert(service);
        return Ok(());
    }
    else
    {
        return Err(Cause::ServiceAlreadyRegistered)
    }
}

/* deregister a service so that its capsule is no longer responsible for it
   => sid = service to deregister
   <= Ok for success, or an error code for failure */
pub fn deregister(sid: ServiceID) -> Result<(), Cause>
{
    match SERVICES.lock().remove(&sid)
    {
        None => Err(Cause::ServiceNotFound),
        _ => Ok(())
    }
}

/* send the given message msg to a registered service */
pub fn send(msg: message::Message) -> Result<(), Cause>
{
    let sid = match msg.get_receiver()
    {
        message::Recipient::Service(sid) => sid,
        _ => return Err(Cause::MessageBadType)
    };

    if let Some(service) = SERVICES.lock().get_mut(&sid)
    {
        service.queue(msg);
        Ok(())
    }
    else
    {
        return Err(Cause::ServiceNotAllowed)
    }
}<|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::client_extensions::CLIENT_EXTENSION_DIRECTIVE_NAME;
use crate::connections::CONNECTION_METADATA_DIRECTIVE_NAME;
use crate::handle_fields::HANDLE_FIELD_DIRECTIVE_NAME;
use crate::inline_data_fragment::INLINE_DATA_CONSTANTS;
use crate::match_::MATCH_CONSTANTS;
use crate::react_flight::{
    REACT_FLIGHT_LOCAL_COMPONENTS_METADATA_KEY, REACT_FLIGHT_SCALAR_FLIGHT_FIELD_METADATA_KEY,
};
use crate::refetchable_fragment::CONSTANTS as REFETCHABLE_CONSTANTS;
use crate::relay_client_component::RELAY_CLIENT_COMPONENT_METADATA_KEY;
use crate::relay_resolvers::RELAY_RESOLVER_METADATA_DIRECTIVE_NAME;
use crate::required_directive::{
    CHILDREN_CAN_BUBBLE_METADATA_KEY, REQUIRED_DIRECTIVE_NAME, REQUIRED_METADATA_KEY,
};
use crate::{DIRECTIVE_SPLIT_OPERATION, INTERNAL_METADATA_DIRECTIVE};

use fnv::FnvHashSet;
use graphql_ir::{
    Argument, Directive, Value, ARGUMENT_DEFINITION, UNUSED_LOCAL_VARIABLE_DEPRECATED,
};
use interner::{Intern, StringKey};
use lazy_static::lazy_static;
use schema::{SDLSchema, Schema, Type};

// A wrapper type that allows comparing pointer equality of references. Two
// `PointerAddress` values are equal if they point to the same memory location.
//
// This type is _sound_, but misuse can easily lead to logical bugs if the memory
// of one PointerAddress could not have been freed and reused for a subsequent
// PointerAddress.
#[derive(Hash, Eq, PartialEq, Clone, Copy)]
pub struct PointerAddress(usize);

impl PointerAddress {
    pub fn new<T>(ptr: &T) -> Self {
        let ptr_address: usize = unsafe { std::mem::transmute(ptr) };
        Self(ptr_address)
    }
}

/// This function will return a new Vec[...] of directives,
/// where one will be missing. The one with `remove_directive_name` name
pub fn remove_directive(
    directives: &[Directive],
    remove_directive_name: StringKey,
) -> Vec<Directive> {
    let mut next_directives = Vec::with_capacity(directives.len() - 1);
    for directive in directives {
        if directive.name.item != remove_directive_name {
            next_directives.push(directive.clone());
        }
    }
    next_directives
}

/// Function will create a new Vec[...] of directives
/// when one of them will be replaced with the `replacement`. If the name of
/// `replacement` is matched with the item in the list
pub fn replace_directive(directives: &[Directive], replacement: Directive) -> Vec<Directive> {
    directives
        .iter()
        .map(|directive| {
            if directive.name.item == replacement.name.item {
                return replacement.to_owned();
            }
            directive.to_owned()
        })
        .collect()
}

/// The function that will return a variable name for an argument
/// it it uses a variable (and it the argument is available)
pub fn extract_variable_name(argument: Option<&Argument>) -> Option<StringKey> {
    match argument {
        Some(arg) => match &arg.value.item {
            Value::Variable(var) => Some(var.name.item),
            _ => None,
        },
        None => None,
    }
}

pub struct CustomMetadataDirectives;

impl CustomMetadataDirectives {
    pub fn is_custom_metadata_directive(name: StringKey) -> bool {
        name == *CLIENT_EXTENSION_DIRECTIVE_NAME
            || name == *CONNECTION_METADATA_DIRECTIVE_NAME
            || name == *HANDLE_FIELD_DIRECTIVE_NAME
            || name == MATCH_CONSTANTS.custom_module_directive_name
            || name == *DIRECTIVE_SPLIT_OPERATION
            || name == REFETCHABLE_CONSTANTS.refetchable_metadata_name
            || name == REFETCHABLE_CONSTANTS.refetchable_operation_metadata_name
            || name == *INTERNAL_METADATA_DIRECTIVE
            || name == *ARGUMENT_DEFINITION
            || name == *REACT_FLIGHT_SCALAR_FLIGHT_FIELD_METADATA_KEY
            || name == *REACT_FLIGHT_LOCAL_COMPONENTS_METADATA_KEY
            || name == *REQUIRED_DIRECTIVE_NAME
            || name == *REQUIRED_METADATA_KEY
            || name == *CHILDREN_CAN_BUBBLE_METADATA_KEY
            || name == *RELAY_RESOLVER_METADATA_DIRECTIVE_NAME
            || name == *RELAY_CLIENT_COMPONENT_METADATA_KEY
            || name == *UNUSED_LOCAL_VARIABLE_DEPRECATED
    }

    pub fn should_skip_in_node_identifier(name: StringKey) -> bool {
        name == *CLIENT_EXTENSION_DIRECTIVE_NAME
            || name == *CONNECTION_METADATA_DIRECTIVE_NAME
            || name == *HANDLE_FIELD_DIRECTIVE_NAME
            || name == REFETCHABLE_CONSTANTS.refetchable_metadata_name
            || name == REFETCHABLE_CONSTANTS.refetchable_operation_metadata_name
            || name == *INTERNAL_METADATA_DIRECTIVE
            || name == *ARGUMENT_DEFINITION
            || name == *REACT_FLIGHT_SCALAR_FLIGHT_FIELD_METADATA_KEY
            || name == *REACT_FLIGHT_LOCAL_COMPONENTS_METADATA_KEY
            || name == *REQUIRED_DIRECTIVE_NAME
            || name == *RELAY_RESOLVER_METADATA_DIRECTIVE_NAME
            || name == *RELAY_CLIENT_COMPONENT_METADATA_KEY
    }

    pub fn is_handle_field_directive(name: StringKey) -> bool {
        name == *HANDLE_FIELD_DIRECTIVE_NAME
    }
}

lazy_static! {
    static ref RELAY_CUSTOM_INLINE_FRAGMENT_DIRECTIVES: FnvHashSet<StringKey> = vec![
        *CLIENT_EXTENSION_DIRECTIVE_NAME,
        MATCH_CONSTANTS.custom_module_directive_name,
        INLINE_DATA_CONSTANTS.internal_directive_name,
        "defer".intern(),
    ]
    .into_iter()
    .collect();
}

pub fn is_relay_custom_inline_fragment_directive(directive: &Directive) -> bool {
    RELAY_CUSTOM_INLINE_FRAGMENT_DIRECTIVES.contains(&directive.name.item)
}

pub fn generate_abstract_type_refinement_key(schema: &SDLSchema, type_: Type) -> StringKey {
    format!("__is{}", schema.get_type_name(type_).lookup()).intern()
}

pub fn get_normalization_operation_name(name: StringKey) -> String {
    format!("{}$normalization", name)
}

pub fn get_fragment_filename(fragment_name: StringKey) -> StringKey {
    format!(
        "{}.graphql",
        get_normalization_operation_name(fragment_name)
    )
    .intern()
}
<commit_msg>small refactor to use array contains for constant compare<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::client_extensions::CLIENT_EXTENSION_DIRECTIVE_NAME;
use crate::connections::CONNECTION_METADATA_DIRECTIVE_NAME;
use crate::handle_fields::HANDLE_FIELD_DIRECTIVE_NAME;
use crate::inline_data_fragment::INLINE_DATA_CONSTANTS;
use crate::match_::MATCH_CONSTANTS;
use crate::react_flight::{
    REACT_FLIGHT_LOCAL_COMPONENTS_METADATA_KEY, REACT_FLIGHT_SCALAR_FLIGHT_FIELD_METADATA_KEY,
};
use crate::refetchable_fragment::CONSTANTS as REFETCHABLE_CONSTANTS;
use crate::relay_client_component::RELAY_CLIENT_COMPONENT_METADATA_KEY;
use crate::relay_resolvers::RELAY_RESOLVER_METADATA_DIRECTIVE_NAME;
use crate::required_directive::{
    CHILDREN_CAN_BUBBLE_METADATA_KEY, REQUIRED_DIRECTIVE_NAME, REQUIRED_METADATA_KEY,
};
use crate::{DIRECTIVE_SPLIT_OPERATION, INTERNAL_METADATA_DIRECTIVE};

use graphql_ir::{
    Argument, Directive, Value, ARGUMENT_DEFINITION, UNUSED_LOCAL_VARIABLE_DEPRECATED,
};
use interner::{Intern, StringKey};
use lazy_static::lazy_static;
use schema::{SDLSchema, Schema, Type};

// A wrapper type that allows comparing pointer equality of references. Two
// `PointerAddress` values are equal if they point to the same memory location.
//
// This type is _sound_, but misuse can easily lead to logical bugs if the memory
// of one PointerAddress could not have been freed and reused for a subsequent
// PointerAddress.
#[derive(Hash, Eq, PartialEq, Clone, Copy)]
pub struct PointerAddress(usize);

impl PointerAddress {
    pub fn new<T>(ptr: &T) -> Self {
        let ptr_address: usize = unsafe { std::mem::transmute(ptr) };
        Self(ptr_address)
    }
}

/// This function will return a new Vec[...] of directives,
/// where one will be missing. The one with `remove_directive_name` name
pub fn remove_directive(
    directives: &[Directive],
    remove_directive_name: StringKey,
) -> Vec<Directive> {
    let mut next_directives = Vec::with_capacity(directives.len() - 1);
    for directive in directives {
        if directive.name.item != remove_directive_name {
            next_directives.push(directive.clone());
        }
    }
    next_directives
}

/// Function will create a new Vec[...] of directives
/// when one of them will be replaced with the `replacement`. If the name of
/// `replacement` is matched with the item in the list
pub fn replace_directive(directives: &[Directive], replacement: Directive) -> Vec<Directive> {
    directives
        .iter()
        .map(|directive| {
            if directive.name.item == replacement.name.item {
                return replacement.to_owned();
            }
            directive.to_owned()
        })
        .collect()
}

/// The function that will return a variable name for an argument
/// it it uses a variable (and it the argument is available)
pub fn extract_variable_name(argument: Option<&Argument>) -> Option<StringKey> {
    match argument {
        Some(arg) => match &arg.value.item {
            Value::Variable(var) => Some(var.name.item),
            _ => None,
        },
        None => None,
    }
}

lazy_static! {
    static ref CUSTOM_METADATA_DIRECTIVES: [StringKey; 17] = [
        *CLIENT_EXTENSION_DIRECTIVE_NAME,
        *CONNECTION_METADATA_DIRECTIVE_NAME,
        *HANDLE_FIELD_DIRECTIVE_NAME,
        MATCH_CONSTANTS.custom_module_directive_name,
        *DIRECTIVE_SPLIT_OPERATION,
        REFETCHABLE_CONSTANTS.refetchable_metadata_name,
        REFETCHABLE_CONSTANTS.refetchable_operation_metadata_name,
        *INTERNAL_METADATA_DIRECTIVE,
        *ARGUMENT_DEFINITION,
        *REACT_FLIGHT_SCALAR_FLIGHT_FIELD_METADATA_KEY,
        *REACT_FLIGHT_LOCAL_COMPONENTS_METADATA_KEY,
        *REQUIRED_DIRECTIVE_NAME,
        *REQUIRED_METADATA_KEY,
        *CHILDREN_CAN_BUBBLE_METADATA_KEY,
        *RELAY_RESOLVER_METADATA_DIRECTIVE_NAME,
        *RELAY_CLIENT_COMPONENT_METADATA_KEY,
        *UNUSED_LOCAL_VARIABLE_DEPRECATED,
    ];
    static ref DIRECTIVES_SKIPPED_IN_NODE_IDENTIFIER: [StringKey; 12] = [
        *CLIENT_EXTENSION_DIRECTIVE_NAME,
        *CONNECTION_METADATA_DIRECTIVE_NAME,
        *HANDLE_FIELD_DIRECTIVE_NAME,
        REFETCHABLE_CONSTANTS.refetchable_metadata_name,
        REFETCHABLE_CONSTANTS.refetchable_operation_metadata_name,
        *INTERNAL_METADATA_DIRECTIVE,
        *ARGUMENT_DEFINITION,
        *REACT_FLIGHT_SCALAR_FLIGHT_FIELD_METADATA_KEY,
        *REACT_FLIGHT_LOCAL_COMPONENTS_METADATA_KEY,
        *REQUIRED_DIRECTIVE_NAME,
        *RELAY_RESOLVER_METADATA_DIRECTIVE_NAME,
        *RELAY_CLIENT_COMPONENT_METADATA_KEY,
    ];
    static ref RELAY_CUSTOM_INLINE_FRAGMENT_DIRECTIVES: [StringKey; 4] = [
        *CLIENT_EXTENSION_DIRECTIVE_NAME,
        MATCH_CONSTANTS.custom_module_directive_name,
        INLINE_DATA_CONSTANTS.internal_directive_name,
        "defer".intern(),
    ];
}

pub struct CustomMetadataDirectives;

impl CustomMetadataDirectives {
    pub fn is_custom_metadata_directive(name: StringKey) -> bool {
        CUSTOM_METADATA_DIRECTIVES.contains(&name)
    }

    pub fn should_skip_in_node_identifier(name: StringKey) -> bool {
        DIRECTIVES_SKIPPED_IN_NODE_IDENTIFIER.contains(&name)
    }

    pub fn is_handle_field_directive(name: StringKey) -> bool {
        name == *HANDLE_FIELD_DIRECTIVE_NAME
    }
}

pub fn is_relay_custom_inline_fragment_directive(directive: &Directive) -> bool {
    RELAY_CUSTOM_INLINE_FRAGMENT_DIRECTIVES.contains(&directive.name.item)
}

pub fn generate_abstract_type_refinement_key(schema: &SDLSchema, type_: Type) -> StringKey {
    format!("__is{}", schema.get_type_name(type_).lookup()).intern()
}

pub fn get_normalization_operation_name(name: StringKey) -> String {
    format!("{}$normalization", name)
}

pub fn get_fragment_filename(fragment_name: StringKey) -> StringKey {
    format!(
        "{}.graphql",
        get_normalization_operation_name(fragment_name)
    )
    .intern()
}
<|endoftext|>


<commit_before>use super::{StringReader, UnmatchedBrace};

use rustc_ast::token::{self, DelimToken, Token};
use rustc_ast::tokenstream::{
    DelimSpan,
    IsJoint::{self, *},
    TokenStream, TokenTree, TreeAndJoint,
};
use rustc_ast_pretty::pprust::token_to_string;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::PResult;
use rustc_span::Span;

impl<'a> StringReader<'a> {
    crate fn into_token_trees(self) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) {
        let mut tt_reader = TokenTreesReader {
            string_reader: self,
            token: Token::dummy(),
            joint_to_prev: Joint,
            open_braces: Vec::new(),
            unmatched_braces: Vec::new(),
            matching_delim_spans: Vec::new(),
            last_unclosed_found_span: None,
            last_delim_empty_block_spans: FxHashMap::default(),
            matching_block_spans: Vec::new(),
        };
        let res = tt_reader.parse_all_token_trees();
        (res, tt_reader.unmatched_braces)
    }
}

struct TokenTreesReader<'a> {
    string_reader: StringReader<'a>,
    token: Token,
    joint_to_prev: IsJoint,
    /// Stack of open delimiters and their spans. Used for error message.
    open_braces: Vec<(token::DelimToken, Span)>,
    unmatched_braces: Vec<UnmatchedBrace>,
    /// The type and spans for all braces
    ///
    /// Used only for error recovery when arriving to EOF with mismatched braces.
    matching_delim_spans: Vec<(token::DelimToken, Span, Span)>,
    last_unclosed_found_span: Option<Span>,
    /// Collect empty block spans that might have been auto-inserted by editors.
    last_delim_empty_block_spans: FxHashMap<token::DelimToken, Span>,
    /// Collect the spans of braces (Open, Close). Used only
    /// for detecting if blocks are empty and only braces.
    matching_block_spans: Vec<(Span, Span)>,
}

impl<'a> TokenTreesReader<'a> {
    // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`.
    fn parse_all_token_trees(&mut self) -> PResult<'a, TokenStream> {
        let mut buf = TokenStreamBuilder::default();

        self.real_token();
        while self.token != token::Eof {
            buf.push(self.parse_token_tree()?);
        }

        Ok(buf.into_token_stream())
    }

    // Parse a stream of tokens into a list of `TokenTree`s, up to a `CloseDelim`.
    fn parse_token_trees_until_close_delim(&mut self) -> TokenStream {
        let mut buf = TokenStreamBuilder::default();
        loop {
            if let token::CloseDelim(..) = self.token.kind {
                return buf.into_token_stream();
            }

            match self.parse_token_tree() {
                Ok(tree) => buf.push(tree),
                Err(mut e) => {
                    e.emit();
                    return buf.into_token_stream();
                }
            }
        }
    }

    fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> {
        let sm = self.string_reader.sess.source_map();

        match self.token.kind {
            token::Eof => {
                let msg = "this file contains an unclosed delimiter";
                let mut err =
                    self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, msg);
                for &(_, sp) in &self.open_braces {
                    err.span_label(sp, "unclosed delimiter");
                    self.unmatched_braces.push(UnmatchedBrace {
                        expected_delim: token::DelimToken::Brace,
                        found_delim: None,
                        found_span: self.token.span,
                        unclosed_span: Some(sp),
                        candidate_span: None,
                    });
                }

                if let Some((delim, _)) = self.open_braces.last() {
                    if let Some((_, open_sp, close_sp)) =
                        self.matching_delim_spans.iter().find(|(d, open_sp, close_sp)| {
                            if let Some(close_padding) = sm.span_to_margin(*close_sp) {
                                if let Some(open_padding) = sm.span_to_margin(*open_sp) {
                                    return delim == d && close_padding != open_padding;
                                }
                            }
                            false
                        })
                    // these are in reverse order as they get inserted on close, but
                    {
                        // we want the last open/first close
                        err.span_label(*open_sp, "this delimiter might not be properly closed...");
                        err.span_label(
                            *close_sp,
                            "...as it matches this but it has different indentation",
                        );
                    }
                }
                Err(err)
            }
            token::OpenDelim(delim) => {
                // The span for beginning of the delimited section
                let pre_span = self.token.span;

                // Parse the open delimiter.
                self.open_braces.push((delim, self.token.span));
                self.real_token();

                // Parse the token trees within the delimiters.
                // We stop at any delimiter so we can try to recover if the user
                // uses an incorrect delimiter.
                let tts = self.parse_token_trees_until_close_delim();

                // Expand to cover the entire delimited token tree
                let delim_span = DelimSpan::from_pair(pre_span, self.token.span);

                match self.token.kind {
                    // Correct delimiter.
                    token::CloseDelim(d) if d == delim => {
                        let (open_brace, open_brace_span) = self.open_braces.pop().unwrap();
                        let close_brace_span = self.token.span;

                        if tts.is_empty() {
                            let empty_block_span = open_brace_span.to(close_brace_span);
                            if !sm.is_multiline(empty_block_span) {
                                // Only track if the block is in the form of `{}`, otherwise it is
                                // likely that it was written on purpose.
                                self.last_delim_empty_block_spans.insert(delim, empty_block_span);
                            }
                        }

                        match (open_brace, delim) {
                            //only add braces
                            (DelimToken::Brace, DelimToken::Brace) => {
                                self.matching_block_spans.push((open_brace_span, close_brace_span));
                            }
                            _ => {}
                        }

                        if self.open_braces.is_empty() {
                            // Clear up these spans to avoid suggesting them as we've found
                            // properly matched delimiters so far for an entire block.
                            self.matching_delim_spans.clear();
                        } else {
                            self.matching_delim_spans.push((
                                open_brace,
                                open_brace_span,
                                close_brace_span,
                            ));
                        }
                        // Parse the closing delimiter.
                        self.real_token();
                    }
                    // Incorrect delimiter.
                    token::CloseDelim(other) => {
                        let mut unclosed_delimiter = None;
                        let mut candidate = None;

                        if self.last_unclosed_found_span != Some(self.token.span) {
                            // do not complain about the same unclosed delimiter multiple times
                            self.last_unclosed_found_span = Some(self.token.span);
                            // This is a conservative error: only report the last unclosed
                            // delimiter. The previous unclosed delimiters could actually be
                            // closed! The parser just hasn't gotten to them yet.
                            if let Some(&(_, sp)) = self.open_braces.last() {
                                unclosed_delimiter = Some(sp);
                            };
                            if let Some(current_padding) = sm.span_to_margin(self.token.span) {
                                for (brace, brace_span) in &self.open_braces {
                                    if let Some(padding) = sm.span_to_margin(*brace_span) {
                                        // high likelihood of these two corresponding
                                        if current_padding == padding && brace == &other {
                                            candidate = Some(*brace_span);
                                        }
                                    }
                                }
                            }
                            let (tok, _) = self.open_braces.pop().unwrap();
                            self.unmatched_braces.push(UnmatchedBrace {
                                expected_delim: tok,
                                found_delim: Some(other),
                                found_span: self.token.span,
                                unclosed_span: unclosed_delimiter,
                                candidate_span: candidate,
                            });
                        } else {
                            self.open_braces.pop();
                        }

                        // If the incorrect delimiter matches an earlier opening
                        // delimiter, then don't consume it (it can be used to
                        // close the earlier one). Otherwise, consume it.
                        // E.g., we try to recover from:
                        // fn foo() {
                        //     bar(baz(
                        // }  // Incorrect delimiter but matches the earlier `{`
                        if !self.open_braces.iter().any(|&(b, _)| b == other) {
                            self.real_token();
                        }
                    }
                    token::Eof => {
                        // Silently recover, the EOF token will be seen again
                        // and an error emitted then. Thus we don't pop from
                        // self.open_braces here.
                    }
                    _ => {}
                }

                Ok(TokenTree::Delimited(delim_span, delim, tts).into())
            }
            token::CloseDelim(delim) => {
                // An unexpected closing delimiter (i.e., there is no
                // matching opening delimiter).
                let token_str = token_to_string(&self.token);
                let msg = format!("unexpected closing delimiter: `{}`", token_str);
                let mut err =
                    self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, &msg);

                // Braces are added at the end, so the last element is the biggest block
                if let Some(parent) = self.matching_block_spans.last() {
                    if let Some(span) = self.last_delim_empty_block_spans.remove(&delim) {
                        // Check if the (empty block) is in the last properly closed block
                        if (parent.0.to(parent.1)).contains(span) {
                            err.span_label(
                                span,
                                "block is empty, you might have not meant to close it",
                            );
                        } else {
                            err.span_label(parent.0, "this opening brace...");

                            err.span_label(parent.1, "...matches this closing brace");
                        }
                    } else {
                        err.span_label(parent.0, "this opening brace...");

                        err.span_label(parent.1, "...matches this closing brace");
                    }
                }

                err.span_label(self.token.span, "unexpected closing delimiter");
                Err(err)
            }
            _ => {
                let tt = TokenTree::Token(self.token.take());
                self.real_token();
                let is_joint = self.joint_to_prev == Joint && self.token.is_op();
                Ok((tt, if is_joint { Joint } else { NonJoint }))
            }
        }
    }

    fn real_token(&mut self) {
        let (joint_to_prev, token) = self.string_reader.next_token();
        self.joint_to_prev = joint_to_prev;
        self.token = token;
    }
}

#[derive(Default)]
struct TokenStreamBuilder {
    buf: Vec<TreeAndJoint>,
}

impl TokenStreamBuilder {
    fn push(&mut self, (tree, joint): TreeAndJoint) {
        if let Some((TokenTree::Token(prev_token), Joint)) = self.buf.last() {
            if let TokenTree::Token(token) = &tree {
                if let Some(glued) = prev_token.glue(token) {
                    self.buf.pop();
                    self.buf.push((TokenTree::Token(glued), joint));
                    return;
                }
            }
        }
        self.buf.push((tree, joint))
    }

    fn into_token_stream(self) -> TokenStream {
        TokenStream::new(self.buf)
    }
}
<commit_msg>Simplify TokenTreesReader<commit_after>use super::{StringReader, UnmatchedBrace};

use rustc_ast::token::{self, DelimToken, Token};
use rustc_ast::tokenstream::{
    DelimSpan,
    IsJoint::{self, *},
    TokenStream, TokenTree, TreeAndJoint,
};
use rustc_ast_pretty::pprust::token_to_string;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::PResult;
use rustc_span::Span;

impl<'a> StringReader<'a> {
    crate fn into_token_trees(self) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) {
        let mut tt_reader = TokenTreesReader {
            string_reader: self,
            token: Token::dummy(),
            open_braces: Vec::new(),
            unmatched_braces: Vec::new(),
            matching_delim_spans: Vec::new(),
            last_unclosed_found_span: None,
            last_delim_empty_block_spans: FxHashMap::default(),
            matching_block_spans: Vec::new(),
        };
        let res = tt_reader.parse_all_token_trees();
        (res, tt_reader.unmatched_braces)
    }
}

struct TokenTreesReader<'a> {
    string_reader: StringReader<'a>,
    token: Token,
    /// Stack of open delimiters and their spans. Used for error message.
    open_braces: Vec<(token::DelimToken, Span)>,
    unmatched_braces: Vec<UnmatchedBrace>,
    /// The type and spans for all braces
    ///
    /// Used only for error recovery when arriving to EOF with mismatched braces.
    matching_delim_spans: Vec<(token::DelimToken, Span, Span)>,
    last_unclosed_found_span: Option<Span>,
    /// Collect empty block spans that might have been auto-inserted by editors.
    last_delim_empty_block_spans: FxHashMap<token::DelimToken, Span>,
    /// Collect the spans of braces (Open, Close). Used only
    /// for detecting if blocks are empty and only braces.
    matching_block_spans: Vec<(Span, Span)>,
}

impl<'a> TokenTreesReader<'a> {
    // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`.
    fn parse_all_token_trees(&mut self) -> PResult<'a, TokenStream> {
        let mut buf = TokenStreamBuilder::default();

        self.bump();
        while self.token != token::Eof {
            buf.push(self.parse_token_tree()?);
        }

        Ok(buf.into_token_stream())
    }

    // Parse a stream of tokens into a list of `TokenTree`s, up to a `CloseDelim`.
    fn parse_token_trees_until_close_delim(&mut self) -> TokenStream {
        let mut buf = TokenStreamBuilder::default();
        loop {
            if let token::CloseDelim(..) = self.token.kind {
                return buf.into_token_stream();
            }

            match self.parse_token_tree() {
                Ok(tree) => buf.push(tree),
                Err(mut e) => {
                    e.emit();
                    return buf.into_token_stream();
                }
            }
        }
    }

    fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> {
        let sm = self.string_reader.sess.source_map();

        match self.token.kind {
            token::Eof => {
                let msg = "this file contains an unclosed delimiter";
                let mut err =
                    self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, msg);
                for &(_, sp) in &self.open_braces {
                    err.span_label(sp, "unclosed delimiter");
                    self.unmatched_braces.push(UnmatchedBrace {
                        expected_delim: token::DelimToken::Brace,
                        found_delim: None,
                        found_span: self.token.span,
                        unclosed_span: Some(sp),
                        candidate_span: None,
                    });
                }

                if let Some((delim, _)) = self.open_braces.last() {
                    if let Some((_, open_sp, close_sp)) =
                        self.matching_delim_spans.iter().find(|(d, open_sp, close_sp)| {
                            if let Some(close_padding) = sm.span_to_margin(*close_sp) {
                                if let Some(open_padding) = sm.span_to_margin(*open_sp) {
                                    return delim == d && close_padding != open_padding;
                                }
                            }
                            false
                        })
                    // these are in reverse order as they get inserted on close, but
                    {
                        // we want the last open/first close
                        err.span_label(*open_sp, "this delimiter might not be properly closed...");
                        err.span_label(
                            *close_sp,
                            "...as it matches this but it has different indentation",
                        );
                    }
                }
                Err(err)
            }
            token::OpenDelim(delim) => {
                // The span for beginning of the delimited section
                let pre_span = self.token.span;

                // Parse the open delimiter.
                self.open_braces.push((delim, self.token.span));
                self.bump();

                // Parse the token trees within the delimiters.
                // We stop at any delimiter so we can try to recover if the user
                // uses an incorrect delimiter.
                let tts = self.parse_token_trees_until_close_delim();

                // Expand to cover the entire delimited token tree
                let delim_span = DelimSpan::from_pair(pre_span, self.token.span);

                match self.token.kind {
                    // Correct delimiter.
                    token::CloseDelim(d) if d == delim => {
                        let (open_brace, open_brace_span) = self.open_braces.pop().unwrap();
                        let close_brace_span = self.token.span;

                        if tts.is_empty() {
                            let empty_block_span = open_brace_span.to(close_brace_span);
                            if !sm.is_multiline(empty_block_span) {
                                // Only track if the block is in the form of `{}`, otherwise it is
                                // likely that it was written on purpose.
                                self.last_delim_empty_block_spans.insert(delim, empty_block_span);
                            }
                        }

                        match (open_brace, delim) {
                            //only add braces
                            (DelimToken::Brace, DelimToken::Brace) => {
                                self.matching_block_spans.push((open_brace_span, close_brace_span));
                            }
                            _ => {}
                        }

                        if self.open_braces.is_empty() {
                            // Clear up these spans to avoid suggesting them as we've found
                            // properly matched delimiters so far for an entire block.
                            self.matching_delim_spans.clear();
                        } else {
                            self.matching_delim_spans.push((
                                open_brace,
                                open_brace_span,
                                close_brace_span,
                            ));
                        }
                        // Parse the closing delimiter.
                        self.bump();
                    }
                    // Incorrect delimiter.
                    token::CloseDelim(other) => {
                        let mut unclosed_delimiter = None;
                        let mut candidate = None;

                        if self.last_unclosed_found_span != Some(self.token.span) {
                            // do not complain about the same unclosed delimiter multiple times
                            self.last_unclosed_found_span = Some(self.token.span);
                            // This is a conservative error: only report the last unclosed
                            // delimiter. The previous unclosed delimiters could actually be
                            // closed! The parser just hasn't gotten to them yet.
                            if let Some(&(_, sp)) = self.open_braces.last() {
                                unclosed_delimiter = Some(sp);
                            };
                            if let Some(current_padding) = sm.span_to_margin(self.token.span) {
                                for (brace, brace_span) in &self.open_braces {
                                    if let Some(padding) = sm.span_to_margin(*brace_span) {
                                        // high likelihood of these two corresponding
                                        if current_padding == padding && brace == &other {
                                            candidate = Some(*brace_span);
                                        }
                                    }
                                }
                            }
                            let (tok, _) = self.open_braces.pop().unwrap();
                            self.unmatched_braces.push(UnmatchedBrace {
                                expected_delim: tok,
                                found_delim: Some(other),
                                found_span: self.token.span,
                                unclosed_span: unclosed_delimiter,
                                candidate_span: candidate,
                            });
                        } else {
                            self.open_braces.pop();
                        }

                        // If the incorrect delimiter matches an earlier opening
                        // delimiter, then don't consume it (it can be used to
                        // close the earlier one). Otherwise, consume it.
                        // E.g., we try to recover from:
                        // fn foo() {
                        //     bar(baz(
                        // }  // Incorrect delimiter but matches the earlier `{`
                        if !self.open_braces.iter().any(|&(b, _)| b == other) {
                            self.bump();
                        }
                    }
                    token::Eof => {
                        // Silently recover, the EOF token will be seen again
                        // and an error emitted then. Thus we don't pop from
                        // self.open_braces here.
                    }
                    _ => {}
                }

                Ok(TokenTree::Delimited(delim_span, delim, tts).into())
            }
            token::CloseDelim(delim) => {
                // An unexpected closing delimiter (i.e., there is no
                // matching opening delimiter).
                let token_str = token_to_string(&self.token);
                let msg = format!("unexpected closing delimiter: `{}`", token_str);
                let mut err =
                    self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, &msg);

                // Braces are added at the end, so the last element is the biggest block
                if let Some(parent) = self.matching_block_spans.last() {
                    if let Some(span) = self.last_delim_empty_block_spans.remove(&delim) {
                        // Check if the (empty block) is in the last properly closed block
                        if (parent.0.to(parent.1)).contains(span) {
                            err.span_label(
                                span,
                                "block is empty, you might have not meant to close it",
                            );
                        } else {
                            err.span_label(parent.0, "this opening brace...");

                            err.span_label(parent.1, "...matches this closing brace");
                        }
                    } else {
                        err.span_label(parent.0, "this opening brace...");

                        err.span_label(parent.1, "...matches this closing brace");
                    }
                }

                err.span_label(self.token.span, "unexpected closing delimiter");
                Err(err)
            }
            _ => {
                let tt = TokenTree::Token(self.token.take());
                let mut is_joint = self.bump();
                if !self.token.is_op() {
                    is_joint = NonJoint;
                }
                Ok((tt, is_joint))
            }
        }
    }

    fn bump(&mut self) -> IsJoint {
        let (joint_to_prev, token) = self.string_reader.next_token();
        self.token = token;
        joint_to_prev
    }
}

#[derive(Default)]
struct TokenStreamBuilder {
    buf: Vec<TreeAndJoint>,
}

impl TokenStreamBuilder {
    fn push(&mut self, (tree, joint): TreeAndJoint) {
        if let Some((TokenTree::Token(prev_token), Joint)) = self.buf.last() {
            if let TokenTree::Token(token) = &tree {
                if let Some(glued) = prev_token.glue(token) {
                    self.buf.pop();
                    self.buf.push((TokenTree::Token(glued), joint));
                    return;
                }
            }
        }
        self.buf.push((tree, joint))
    }

    fn into_token_stream(self) -> TokenStream {
        TokenStream::new(self.buf)
    }
}
<|endoftext|>