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

use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::Bindings::NodeListBinding;
use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
use dom::bindings::js::{JS, MutNullableJS, Root, RootedReference};
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::node::{ChildrenMutation, Node};
use dom::window::Window;
use dom_struct::dom_struct;
use std::cell::Cell;

#[derive(JSTraceable, HeapSizeOf)]
#[must_root]
pub enum NodeListType {
    Simple(Vec<JS<Node>>),
    Children(ChildrenList),
}

// https://dom.spec.whatwg.org/#interface-nodelist
#[dom_struct]
pub struct NodeList {
    reflector_: Reflector,
    list_type: NodeListType,
}

impl NodeList {
    #[allow(unrooted_must_root)]
    pub fn new_inherited(list_type: NodeListType) -> NodeList {
        NodeList {
            reflector_: Reflector::new(),
            list_type: list_type,
        }
    }

    #[allow(unrooted_must_root)]
    pub fn new(window: &Window, list_type: NodeListType) -> Root<NodeList> {
        reflect_dom_object(box NodeList::new_inherited(list_type),
                           window,
                           NodeListBinding::Wrap)
    }

    pub fn new_simple_list<T>(window: &Window, iter: T) -> Root<NodeList>
                              where T: Iterator<Item=Root<Node>> {
        NodeList::new(window, NodeListType::Simple(iter.map(|r| JS::from_ref(&*r)).collect()))
    }

    pub fn new_simple_list_slice(window: &Window, slice: &[&Node]) -> Root<NodeList> {
        NodeList::new(window, NodeListType::Simple(slice.iter().map(|r| JS::from_ref(*r)).collect()))
    }

    pub fn new_child_list(window: &Window, node: &Node) -> Root<NodeList> {
        NodeList::new(window, NodeListType::Children(ChildrenList::new(node)))
    }

    pub fn empty(window: &Window) -> Root<NodeList> {
        NodeList::new(window, NodeListType::Simple(vec![]))
    }
}

impl NodeListMethods for NodeList {
    // https://dom.spec.whatwg.org/#dom-nodelist-length
    fn Length(&self) -> u32 {
        match self.list_type {
            NodeListType::Simple(ref elems) => elems.len() as u32,
            NodeListType::Children(ref list) => list.len(),
        }
    }

    // https://dom.spec.whatwg.org/#dom-nodelist-item
    fn Item(&self, index: u32) -> Option<Root<Node>> {
        match self.list_type {
            NodeListType::Simple(ref elems) => {
                elems.get(index as usize).map(|node| Root::from_ref(&**node))
            },
            NodeListType::Children(ref list) => list.item(index),
        }
    }

    // https://dom.spec.whatwg.org/#dom-nodelist-item
    fn IndexedGetter(&self, index: u32) -> Option<Root<Node>> {
        self.Item(index)
    }
}

impl NodeList {
    pub fn as_children_list(&self) -> &ChildrenList {
        if let NodeListType::Children(ref list) = self.list_type {
            list
        } else {
            panic!("called as_children_list() on a simple node list")
        }
    }

    pub fn as_simple_list(&self) -> &Vec<JS<Node>> {
        if let NodeListType::Simple(ref list) = self.list_type {
            list
        } else {
            panic!("called as_simple_list() on a children node list")
        }
    }

    pub fn iter(&self) -> NodeListIterator {
        NodeListIterator {
            nodes: self,
            offset: 0,
        }
    }
}

#[derive(JSTraceable, HeapSizeOf)]
#[must_root]
pub struct ChildrenList {
    node: JS<Node>,
    #[ignore_heap_size_of = "Defined in rust-mozjs"]
    last_visited: MutNullableJS<Node>,
    last_index: Cell<u32>,
}

impl ChildrenList {
    pub fn new(node: &Node) -> ChildrenList {
        let last_visited = node.GetFirstChild();
        ChildrenList {
            node: JS::from_ref(node),
            last_visited: MutNullableJS::new(last_visited.r()),
            last_index: Cell::new(0u32),
        }
    }

    pub fn len(&self) -> u32 {
        self.node.children_count()
    }

    pub fn item(&self, index: u32) -> Option<Root<Node>> {
        // This always start traversing the children from the closest element
        // among parent's first and last children and the last visited one.
        let len = self.len() as u32;
        if index >= len {
            return None;
        }
        if index == 0u32 {
            // Item is first child if any, not worth updating last visited.
            return self.node.GetFirstChild();
        }
        let last_index = self.last_index.get();
        if index == last_index {
            // Item is last visited child, no need to update last visited.
            return Some(self.last_visited.get().unwrap());
        }
        let last_visited = if index - 1u32 == last_index {
            // Item is last visited's next sibling.
            self.last_visited.get().unwrap().GetNextSibling().unwrap()
        } else if last_index > 0 && index == last_index - 1u32 {
            // Item is last visited's previous sibling.
            self.last_visited.get().unwrap().GetPreviousSibling().unwrap()
        } else if index > last_index {
            if index == len - 1u32 {
                // Item is parent's last child, not worth updating last visited.
                return Some(self.node.GetLastChild().unwrap());
            }
            if index <= last_index + (len - last_index) / 2u32 {
                // Item is closer to the last visited child and follows it.
                self.last_visited.get().unwrap()
                                 .inclusively_following_siblings()
                                 .nth((index - last_index) as usize).unwrap()
            } else {
                // Item is closer to parent's last child and obviously
                // precedes it.
                self.node.GetLastChild().unwrap()
                    .inclusively_preceding_siblings()
                    .nth((len - index - 1u32) as usize).unwrap()
            }
        } else if index >= last_index / 2u32 {
            // Item is closer to the last visited child and precedes it.
            self.last_visited.get().unwrap()
                             .inclusively_preceding_siblings()
                             .nth((last_index - index) as usize).unwrap()
        } else {
            // Item is closer to parent's first child and obviously follows it.
            debug_assert!(index < last_index / 2u32);
            self.node.GetFirstChild().unwrap()
                     .inclusively_following_siblings()
                     .nth(index as usize)
                     .unwrap()
        };
        self.last_visited.set(Some(&last_visited));
        self.last_index.set(index);
        Some(last_visited)
    }

    pub fn children_changed(&self, mutation: &ChildrenMutation) {
        fn prepend(list: &ChildrenList, added: &[&Node], next: &Node) {
            let len = added.len() as u32;
            if len == 0u32 {
                return;
            }
            let index = list.last_index.get();
            if index < len {
                list.last_visited.set(Some(added[index as usize]));
            } else if index / 2u32 >= len {
                // If last index is twice as large as the number of added nodes,
                // updating only it means that less nodes will be traversed if
                // caller is traversing the node list linearly.
                list.last_index.set(len + index);
            } else {
                // If last index is not twice as large but still larger,
                // it's better to update it to the number of added nodes.
                list.last_visited.set(Some(next));
                list.last_index.set(len);
            }
        }

        fn replace(list: &ChildrenList,
                   prev: Option<&Node>,
                   removed: &Node,
                   added: &[&Node],
                   next: Option<&Node>) {
            let index = list.last_index.get();
            if removed == &*list.last_visited.get().unwrap() {
                let visited = match (prev, added, next) {
                    (None, _, None) => {
                        // Such cases where parent had only one child should
                        // have been changed into ChildrenMutation::ReplaceAll
                        // by ChildrenMutation::replace().
                        unreachable!()
                    },
                    (_, added, _) if !added.is_empty() => added[0],
                    (_, _, Some(next)) => next,
                    (Some(prev), _, None) => {
                        list.last_index.set(index - 1u32);
                        prev
                    },
                };
                list.last_visited.set(Some(visited));
            } else if added.len() != 1 {
                // The replaced child isn't the last visited one, and there are
                // 0 or more than 1 nodes to replace it. Special care must be
                // given to update the state of that ChildrenList.
                match (prev, next) {
                    (Some(_), None) => {},
                    (None, Some(next)) => {
                        list.last_index.set(index - 1);
                        prepend(list, added, next);
                    },
                    (Some(_), Some(_)) => {
                        list.reset();
                    },
                    (None, None) => unreachable!(),
                }
            }
        }

        match *mutation {
            ChildrenMutation::Append { .. } => {},
            ChildrenMutation::Insert { .. } => {
                self.reset();
            },
            ChildrenMutation::Prepend { added, next } => {
                prepend(self, added, next);
            },
            ChildrenMutation::Replace { prev, removed, added, next } => {
                replace(self, prev, removed, added, next);
            },
            ChildrenMutation::ReplaceAll { added, .. } => {
                let len = added.len();
                let index = self.last_index.get();
                if len == 0 {
                    self.last_visited.set(None);
                    self.last_index.set(0u32);
                } else if index < len as u32 {
                    self.last_visited.set(Some(added[index as usize]));
                } else {
                    // Setting last visited to parent's last child serves no purpose,
                    // so the middle is arbitrarily chosen here in case the caller
                    // wants random access.
                    let middle = len / 2;
                    self.last_visited.set(Some(added[middle]));
                    self.last_index.set(middle as u32);
                }
            },
        }
    }

    fn reset(&self) {
        self.last_visited.set(self.node.GetFirstChild().r());
        self.last_index.set(0u32);
    }
}

pub struct NodeListIterator<'a> {
    nodes: &'a NodeList,
    offset: u32,
}

impl<'a> Iterator for NodeListIterator<'a> {
    type Item = Root<Node>;

    fn next(&mut self) -> Option<Root<Node>> {
        let result = self.nodes.Item(self.offset);
        self.offset = self.offset + 1;
        result
    }
}
<commit_msg>Replace iterator struct with anonymous return iterator type.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::Bindings::NodeListBinding;
use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
use dom::bindings::js::{JS, MutNullableJS, Root, RootedReference};
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::node::{ChildrenMutation, Node};
use dom::window::Window;
use dom_struct::dom_struct;
use std::cell::Cell;

#[derive(JSTraceable, HeapSizeOf)]
#[must_root]
pub enum NodeListType {
    Simple(Vec<JS<Node>>),
    Children(ChildrenList),
}

// https://dom.spec.whatwg.org/#interface-nodelist
#[dom_struct]
pub struct NodeList {
    reflector_: Reflector,
    list_type: NodeListType,
}

impl NodeList {
    #[allow(unrooted_must_root)]
    pub fn new_inherited(list_type: NodeListType) -> NodeList {
        NodeList {
            reflector_: Reflector::new(),
            list_type: list_type,
        }
    }

    #[allow(unrooted_must_root)]
    pub fn new(window: &Window, list_type: NodeListType) -> Root<NodeList> {
        reflect_dom_object(box NodeList::new_inherited(list_type),
                           window,
                           NodeListBinding::Wrap)
    }

    pub fn new_simple_list<T>(window: &Window, iter: T) -> Root<NodeList>
                              where T: Iterator<Item=Root<Node>> {
        NodeList::new(window, NodeListType::Simple(iter.map(|r| JS::from_ref(&*r)).collect()))
    }

    pub fn new_simple_list_slice(window: &Window, slice: &[&Node]) -> Root<NodeList> {
        NodeList::new(window, NodeListType::Simple(slice.iter().map(|r| JS::from_ref(*r)).collect()))
    }

    pub fn new_child_list(window: &Window, node: &Node) -> Root<NodeList> {
        NodeList::new(window, NodeListType::Children(ChildrenList::new(node)))
    }

    pub fn empty(window: &Window) -> Root<NodeList> {
        NodeList::new(window, NodeListType::Simple(vec![]))
    }
}

impl NodeListMethods for NodeList {
    // https://dom.spec.whatwg.org/#dom-nodelist-length
    fn Length(&self) -> u32 {
        match self.list_type {
            NodeListType::Simple(ref elems) => elems.len() as u32,
            NodeListType::Children(ref list) => list.len(),
        }
    }

    // https://dom.spec.whatwg.org/#dom-nodelist-item
    fn Item(&self, index: u32) -> Option<Root<Node>> {
        match self.list_type {
            NodeListType::Simple(ref elems) => {
                elems.get(index as usize).map(|node| Root::from_ref(&**node))
            },
            NodeListType::Children(ref list) => list.item(index),
        }
    }

    // https://dom.spec.whatwg.org/#dom-nodelist-item
    fn IndexedGetter(&self, index: u32) -> Option<Root<Node>> {
        self.Item(index)
    }
}

impl NodeList {
    pub fn as_children_list(&self) -> &ChildrenList {
        if let NodeListType::Children(ref list) = self.list_type {
            list
        } else {
            panic!("called as_children_list() on a simple node list")
        }
    }

    pub fn as_simple_list(&self) -> &Vec<JS<Node>> {
        if let NodeListType::Simple(ref list) = self.list_type {
            list
        } else {
            panic!("called as_simple_list() on a children node list")
        }
    }

    pub fn iter<'a>(&'a self) -> impl Iterator<Item=Root<Node>> + 'a {
        let len = self.Length();
        (0..len).flat_map(move |i| self.Item(i))
    }
}

#[derive(JSTraceable, HeapSizeOf)]
#[must_root]
pub struct ChildrenList {
    node: JS<Node>,
    #[ignore_heap_size_of = "Defined in rust-mozjs"]
    last_visited: MutNullableJS<Node>,
    last_index: Cell<u32>,
}

impl ChildrenList {
    pub fn new(node: &Node) -> ChildrenList {
        let last_visited = node.GetFirstChild();
        ChildrenList {
            node: JS::from_ref(node),
            last_visited: MutNullableJS::new(last_visited.r()),
            last_index: Cell::new(0u32),
        }
    }

    pub fn len(&self) -> u32 {
        self.node.children_count()
    }

    pub fn item(&self, index: u32) -> Option<Root<Node>> {
        // This always start traversing the children from the closest element
        // among parent's first and last children and the last visited one.
        let len = self.len() as u32;
        if index >= len {
            return None;
        }
        if index == 0u32 {
            // Item is first child if any, not worth updating last visited.
            return self.node.GetFirstChild();
        }
        let last_index = self.last_index.get();
        if index == last_index {
            // Item is last visited child, no need to update last visited.
            return Some(self.last_visited.get().unwrap());
        }
        let last_visited = if index - 1u32 == last_index {
            // Item is last visited's next sibling.
            self.last_visited.get().unwrap().GetNextSibling().unwrap()
        } else if last_index > 0 && index == last_index - 1u32 {
            // Item is last visited's previous sibling.
            self.last_visited.get().unwrap().GetPreviousSibling().unwrap()
        } else if index > last_index {
            if index == len - 1u32 {
                // Item is parent's last child, not worth updating last visited.
                return Some(self.node.GetLastChild().unwrap());
            }
            if index <= last_index + (len - last_index) / 2u32 {
                // Item is closer to the last visited child and follows it.
                self.last_visited.get().unwrap()
                                 .inclusively_following_siblings()
                                 .nth((index - last_index) as usize).unwrap()
            } else {
                // Item is closer to parent's last child and obviously
                // precedes it.
                self.node.GetLastChild().unwrap()
                    .inclusively_preceding_siblings()
                    .nth((len - index - 1u32) as usize).unwrap()
            }
        } else if index >= last_index / 2u32 {
            // Item is closer to the last visited child and precedes it.
            self.last_visited.get().unwrap()
                             .inclusively_preceding_siblings()
                             .nth((last_index - index) as usize).unwrap()
        } else {
            // Item is closer to parent's first child and obviously follows it.
            debug_assert!(index < last_index / 2u32);
            self.node.GetFirstChild().unwrap()
                     .inclusively_following_siblings()
                     .nth(index as usize)
                     .unwrap()
        };
        self.last_visited.set(Some(&last_visited));
        self.last_index.set(index);
        Some(last_visited)
    }

    pub fn children_changed(&self, mutation: &ChildrenMutation) {
        fn prepend(list: &ChildrenList, added: &[&Node], next: &Node) {
            let len = added.len() as u32;
            if len == 0u32 {
                return;
            }
            let index = list.last_index.get();
            if index < len {
                list.last_visited.set(Some(added[index as usize]));
            } else if index / 2u32 >= len {
                // If last index is twice as large as the number of added nodes,
                // updating only it means that less nodes will be traversed if
                // caller is traversing the node list linearly.
                list.last_index.set(len + index);
            } else {
                // If last index is not twice as large but still larger,
                // it's better to update it to the number of added nodes.
                list.last_visited.set(Some(next));
                list.last_index.set(len);
            }
        }

        fn replace(list: &ChildrenList,
                   prev: Option<&Node>,
                   removed: &Node,
                   added: &[&Node],
                   next: Option<&Node>) {
            let index = list.last_index.get();
            if removed == &*list.last_visited.get().unwrap() {
                let visited = match (prev, added, next) {
                    (None, _, None) => {
                        // Such cases where parent had only one child should
                        // have been changed into ChildrenMutation::ReplaceAll
                        // by ChildrenMutation::replace().
                        unreachable!()
                    },
                    (_, added, _) if !added.is_empty() => added[0],
                    (_, _, Some(next)) => next,
                    (Some(prev), _, None) => {
                        list.last_index.set(index - 1u32);
                        prev
                    },
                };
                list.last_visited.set(Some(visited));
            } else if added.len() != 1 {
                // The replaced child isn't the last visited one, and there are
                // 0 or more than 1 nodes to replace it. Special care must be
                // given to update the state of that ChildrenList.
                match (prev, next) {
                    (Some(_), None) => {},
                    (None, Some(next)) => {
                        list.last_index.set(index - 1);
                        prepend(list, added, next);
                    },
                    (Some(_), Some(_)) => {
                        list.reset();
                    },
                    (None, None) => unreachable!(),
                }
            }
        }

        match *mutation {
            ChildrenMutation::Append { .. } => {},
            ChildrenMutation::Insert { .. } => {
                self.reset();
            },
            ChildrenMutation::Prepend { added, next } => {
                prepend(self, added, next);
            },
            ChildrenMutation::Replace { prev, removed, added, next } => {
                replace(self, prev, removed, added, next);
            },
            ChildrenMutation::ReplaceAll { added, .. } => {
                let len = added.len();
                let index = self.last_index.get();
                if len == 0 {
                    self.last_visited.set(None);
                    self.last_index.set(0u32);
                } else if index < len as u32 {
                    self.last_visited.set(Some(added[index as usize]));
                } else {
                    // Setting last visited to parent's last child serves no purpose,
                    // so the middle is arbitrarily chosen here in case the caller
                    // wants random access.
                    let middle = len / 2;
                    self.last_visited.set(Some(added[middle]));
                    self.last_index.set(middle as u32);
                }
            },
        }
    }

    fn reset(&self) {
        self.last_visited.set(self.node.GetFirstChild().r());
        self.last_index.set(0u32);
    }
}
<|endoftext|>


<commit_before>//
// Copyright 2018 The Project Oak Authors
//
// 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.
//

//! Functionality to help Oak Nodes interact with gRPC.

pub use crate::proto::code::Code;
use crate::{proto, OakError};
use log::{error, warn};
pub use proto::grpc_encap::{GrpcRequest, GrpcResponse};
use protobuf::ProtobufEnum;

pub mod client;
mod invocation;
pub use invocation::Invocation;

/// Result type that uses a [`proto::status::Status`] type for error values.
pub type Result<T> = std::result::Result<T, proto::status::Status>;

/// Helper to create a gRPC status object.
pub fn build_status(code: Code, msg: &str) -> proto::status::Status {
    let mut status = proto::status::Status::new();
    status.set_code(code.value());
    status.set_message(msg.to_string());
    status
}

/// Channel-holding object that encapsulates response messages into
/// `GrpcResponse` wrapper messages and writes serialized versions to a send
/// channel.
pub struct ChannelResponseWriter {
    sender: crate::io::Sender<GrpcResponse>,
}

/// Indicate whether a write method should leave the current gRPC method
/// invocation open or close it.
#[derive(PartialEq, Clone, Debug)]
pub enum WriteMode {
    KeepOpen,
    Close,
}

impl ChannelResponseWriter {
    pub fn new(sender: crate::io::Sender<GrpcResponse>) -> Self {
        ChannelResponseWriter { sender }
    }

    /// Retrieve the Oak handle underlying the writer object.
    pub fn handle(self) -> crate::WriteHandle {
        self.sender.handle
    }

    /// Write out a gRPC response and optionally close out the method
    /// invocation.  Any errors from the channel are silently dropped.
    pub fn write<T: protobuf::Message>(
        &mut self,
        rsp: &T,
        mode: WriteMode,
    ) -> std::result::Result<(), OakError> {
        // Put the serialized response into a GrpcResponse message wrapper and
        // serialize it into the channel.
        let mut grpc_rsp = GrpcResponse::new();
        let mut any = protobuf::well_known_types::Any::new();
        rsp.write_to_writer(&mut any.value)?;
        grpc_rsp.set_rsp_msg(any);
        grpc_rsp.set_last(match mode {
            WriteMode::KeepOpen => false,
            WriteMode::Close => true,
        });
        self.sender.send(&grpc_rsp)?;
        if mode == WriteMode::Close {
            self.sender.close()?;
        }
        Ok(())
    }

    /// Write an empty gRPC response and optionally close out the method
    /// invocation. Any errors from the channel are silently dropped.
    pub fn write_empty(&mut self, mode: WriteMode) -> std::result::Result<(), OakError> {
        let mut grpc_rsp = GrpcResponse::new();
        grpc_rsp.set_rsp_msg(protobuf::well_known_types::Any::new());
        grpc_rsp.set_last(match mode {
            WriteMode::KeepOpen => false,
            WriteMode::Close => true,
        });
        self.sender.send(&grpc_rsp)?;
        if mode == WriteMode::Close {
            self.sender.close()?;
        }
        Ok(())
    }

    /// Close out the gRPC method invocation with the given final result.
    pub fn close(&mut self, result: Result<()>) -> std::result::Result<(), OakError> {
        // Build a final GrpcResponse message wrapper and serialize it into the
        // channel.
        let mut grpc_rsp = GrpcResponse::new();
        grpc_rsp.set_last(true);
        if let Err(status) = result {
            grpc_rsp.set_status(status);
        }
        self.sender.send(&grpc_rsp)?;
        self.sender.close()?;
        Ok(())
    }
}

/// Trait for Oak Nodes that act as a gRPC services.
///
/// A `ServerNode` instance is normally passed to [`oak::run_event_loop`], to
/// allow repeated invocation of its `invoke()` method.
///
/// You can choose to implement this trait yourself, or use the convenient
/// `Dispatcher` created by the gRPC code generator.
///
/// [`oak::run_event_loop`]: ../../oak/fn.run_event_loop.html
pub trait ServerNode {
    /// Process a single gRPC method invocation.
    ///
    /// The method name is provided by `method` and the incoming serialized gRPC
    /// request is held in `req`.  Response messages should be written using
    /// `writer.write`, followed by `writer.close`.
    fn invoke(&mut self, method: &str, req: &[u8], writer: ChannelResponseWriter);
}

impl<T: ServerNode> crate::Node<Invocation> for T {
    /// Handle incoming gRPC events for an [`ServerNode`].
    ///
    /// Invoking the given `node`'s [`invoke`] method for each incoming request that
    /// arrives on the inbound channel as a serialized [`Invocation`] object,
    /// giving the [`invoke`] method the outbound channel for encapsulated responses
    /// to be written to.
    ///
    /// [`invoke`]: ServerNode::invoke
    fn handle_command(
        &mut self,
        invocation: Invocation,
    ) -> std::result::Result<(), crate::OakError> {
        // Read a single encapsulated request message from the read half.
        let req: GrpcRequest = invocation.request_receiver.receive()?;
        // Since we are expecting a single message, close the channel immediately.
        // This will change when we implement client streaming (#97).
        invocation.request_receiver.close()?;
        if !req.last {
            // TODO(#97): Implement client streaming.
            panic!("Support for streaming requests not yet implemented");
        }
        self.invoke(
            &req.method_name,
            req.get_req_msg().value.as_slice(),
            ChannelResponseWriter::new(invocation.response_sender),
        );
        Ok(())
    }
}

/// Encapsulate a protocol buffer message in a GrpcRequest wrapper using the
/// given method name.
pub fn encap_request<T: protobuf::Message>(req: T, method_name: &str) -> Option<GrpcRequest> {
    // Put the request in a GrpcRequest wrapper and serialize it.
    let mut grpc_req = GrpcRequest::new();
    grpc_req.set_method_name(method_name.to_string());
    let mut any = protobuf::well_known_types::Any::new();
    if let Err(e) = req.write_to_writer(&mut any.value) {
        warn!("failed to serialize gRPC request: {}", e);
        return None;
    };
    grpc_req.set_req_msg(any);
    grpc_req.set_last(true);
    Some(grpc_req)
}

/// Extract a protocol buffer message from a GrpcResponse wrapper.
/// Returns the message together with an indicator of whether this is the last
/// response.
pub fn decap_response<T: protobuf::Message>(mut grpc_rsp: GrpcResponse) -> Result<(T, bool)> {
    if grpc_rsp.get_status().get_code() != Code::OK.value() {
        return Err(grpc_rsp.take_status());
    }
    let rsp = protobuf::parse_from_bytes(&grpc_rsp.get_rsp_msg().value).map_err(|proto_err| {
        build_status(
            Code::INVALID_ARGUMENT,
            &format!("message parsing failed: {}", proto_err),
        )
    })?;
    Ok((rsp, grpc_rsp.get_last()))
}

/// Helper to inject a (single) gRPC request message via a notification channel,
/// in the same manner as the gRPC pseudo-Node does, and return a channel for
/// reading responses from.
pub fn invoke_grpc_method_stream<R>(
    method_name: &str,
    req: R,
    invocation_channel: &crate::io::Sender<Invocation>,
) -> Result<crate::io::Receiver<GrpcResponse>>
where
    R: protobuf::Message,
{
    // Create a new channel for request message delivery.
    let (req_sender, req_receiver) =
        crate::io::channel_create::<GrpcRequest>().expect("failed to create channel");

    // Put the request in a GrpcRequest wrapper and send it into the request
    // message channel.
    let req = encap_request(req, method_name).expect("failed to serialize GrpcRequest");
    req_sender.send(&req).expect("failed to write to channel");
    req_sender.close().expect("failed to close channel");

    // Create a new channel for responses to arrive on.
    let (rsp_sender, rsp_receiver) =
        crate::io::channel_create::<GrpcResponse>().expect("failed to create channel");

    // Build an Invocation holding the two channels and send it down the
    // specified channel.
    let invocation = Invocation {
        request_receiver: req_receiver.clone(),
        response_sender: rsp_sender.clone(),
    };
    invocation_channel
        .send(&invocation)
        .expect("failed to write invocation to channel");
    req_receiver.close().expect("failed to close channel");
    rsp_sender.close().expect("failed to close channel");

    Ok(rsp_receiver)
}

/// Helper to inject a (single) gRPC request message via a notification channel,
/// in the same manner as the gRPC pseudo-Node does, and collect a (single)
/// response.
pub fn invoke_grpc_method<R, Q>(
    method_name: &str,
    req: R,
    invocation_channel: &crate::io::Sender<Invocation>,
) -> Result<Q>
where
    R: protobuf::Message,
    Q: protobuf::Message,
{
    let rsp_receiver = invoke_grpc_method_stream(method_name, req, invocation_channel)?;
    // Read a single encapsulated response.
    let grpc_rsp = rsp_receiver.receive().map_err(|status| {
        error!("failed to receive response: {:?}", status);
        build_status(
            Code::INTERNAL,
            &format!("failed to receive gRPC response: {:?}", status),
        )
    })?;
    rsp_receiver.close().expect("failed to close channel");
    let (rsp, _last) = decap_response(grpc_rsp)?;

    Ok(rsp)
}

/// Generic function that handles request deserialization and response
/// serialization (and sending down a channel) for a function that handles a
/// request/response pair.
///
/// Panics if [de-]serialization or channel operations fail.
pub fn handle_req_rsp<C, R, Q>(mut node_fn: C, req: &[u8], mut writer: ChannelResponseWriter)
where
    C: FnMut(R) -> Result<Q>,
    R: protobuf::Message,
    Q: protobuf::Message,
{
    let r: R = protobuf::parse_from_bytes(&req).expect("Failed to parse request protobuf message");
    let result = match node_fn(r) {
        Ok(rsp) => writer.write(&rsp, WriteMode::Close),
        Err(status) => writer.close(Err(status)),
    };
    if let Err(e) = result {
        panic!("Failed to process response: {:?}", e)
    }
}

/// Generic function that handles request deserialization and response
/// serialization (and sending down a channel) for a function that handles a
/// request and streams responses.
///
/// Panics if [de-]serialization or channel operations fail.
pub fn handle_req_stream<C, R>(mut node_fn: C, req: &[u8], writer: ChannelResponseWriter)
where
    C: FnMut(R, ChannelResponseWriter),
    R: protobuf::Message,
{
    let r: R = protobuf::parse_from_bytes(&req).expect("Failed to parse request protobuf message");
    node_fn(r, writer)
}

/// Generic function that handles request deserialization and response
/// serialization (and sending down a channel) for a function that handles a
/// stream of requests to produce a response.
///
/// Panics if [de-]serialization or channel operations fail.
pub fn handle_stream_rsp<C, R, Q>(mut node_fn: C, req: &[u8], mut writer: ChannelResponseWriter)
where
    C: FnMut(Vec<R>) -> Result<Q>,
    R: protobuf::Message,
    Q: protobuf::Message,
{
    // TODO(#97): better client-side streaming
    let rr: Vec<R> =
        vec![protobuf::parse_from_bytes(&req).expect("Failed to parse request protobuf message")];
    let result = match node_fn(rr) {
        Ok(rsp) => writer.write(&rsp, WriteMode::Close),
        Err(status) => writer.close(Err(status)),
    };
    if let Err(e) = result {
        panic!("Failed to process response: {:?}", e)
    }
}

/// Generic function that handles request deserialization and response
/// serialization (and sending down a channel) for a function that handles a
/// stream of requests to produce a stream of responses.
///
/// Panics if [de-]serialization or channel operations fail.
pub fn handle_stream_stream<C, R>(mut node_fn: C, req: &[u8], writer: ChannelResponseWriter)
where
    C: FnMut(Vec<R>, ChannelResponseWriter),
    R: protobuf::Message,
{
    // TODO(#97): better client-side streaming
    let rr: Vec<R> =
        vec![protobuf::parse_from_bytes(&req).expect("Failed to parse request protobuf message")];
    node_fn(rr, writer)
}
<commit_msg>sdk: close gRPC receiver even on error<commit_after>//
// Copyright 2018 The Project Oak Authors
//
// 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.
//

//! Functionality to help Oak Nodes interact with gRPC.

pub use crate::proto::code::Code;
use crate::{proto, OakError};
use log::{error, warn};
pub use proto::grpc_encap::{GrpcRequest, GrpcResponse};
use protobuf::ProtobufEnum;

pub mod client;
mod invocation;
pub use invocation::Invocation;

/// Result type that uses a [`proto::status::Status`] type for error values.
pub type Result<T> = std::result::Result<T, proto::status::Status>;

/// Helper to create a gRPC status object.
pub fn build_status(code: Code, msg: &str) -> proto::status::Status {
    let mut status = proto::status::Status::new();
    status.set_code(code.value());
    status.set_message(msg.to_string());
    status
}

/// Channel-holding object that encapsulates response messages into
/// `GrpcResponse` wrapper messages and writes serialized versions to a send
/// channel.
pub struct ChannelResponseWriter {
    sender: crate::io::Sender<GrpcResponse>,
}

/// Indicate whether a write method should leave the current gRPC method
/// invocation open or close it.
#[derive(PartialEq, Clone, Debug)]
pub enum WriteMode {
    KeepOpen,
    Close,
}

impl ChannelResponseWriter {
    pub fn new(sender: crate::io::Sender<GrpcResponse>) -> Self {
        ChannelResponseWriter { sender }
    }

    /// Retrieve the Oak handle underlying the writer object.
    pub fn handle(self) -> crate::WriteHandle {
        self.sender.handle
    }

    /// Write out a gRPC response and optionally close out the method
    /// invocation.  Any errors from the channel are silently dropped.
    pub fn write<T: protobuf::Message>(
        &mut self,
        rsp: &T,
        mode: WriteMode,
    ) -> std::result::Result<(), OakError> {
        // Put the serialized response into a GrpcResponse message wrapper and
        // serialize it into the channel.
        let mut grpc_rsp = GrpcResponse::new();
        let mut any = protobuf::well_known_types::Any::new();
        rsp.write_to_writer(&mut any.value)?;
        grpc_rsp.set_rsp_msg(any);
        grpc_rsp.set_last(match mode {
            WriteMode::KeepOpen => false,
            WriteMode::Close => true,
        });
        self.sender.send(&grpc_rsp)?;
        if mode == WriteMode::Close {
            self.sender.close()?;
        }
        Ok(())
    }

    /// Write an empty gRPC response and optionally close out the method
    /// invocation. Any errors from the channel are silently dropped.
    pub fn write_empty(&mut self, mode: WriteMode) -> std::result::Result<(), OakError> {
        let mut grpc_rsp = GrpcResponse::new();
        grpc_rsp.set_rsp_msg(protobuf::well_known_types::Any::new());
        grpc_rsp.set_last(match mode {
            WriteMode::KeepOpen => false,
            WriteMode::Close => true,
        });
        self.sender.send(&grpc_rsp)?;
        if mode == WriteMode::Close {
            self.sender.close()?;
        }
        Ok(())
    }

    /// Close out the gRPC method invocation with the given final result.
    pub fn close(&mut self, result: Result<()>) -> std::result::Result<(), OakError> {
        // Build a final GrpcResponse message wrapper and serialize it into the
        // channel.
        let mut grpc_rsp = GrpcResponse::new();
        grpc_rsp.set_last(true);
        if let Err(status) = result {
            grpc_rsp.set_status(status);
        }
        self.sender.send(&grpc_rsp)?;
        self.sender.close()?;
        Ok(())
    }
}

/// Trait for Oak Nodes that act as a gRPC services.
///
/// A `ServerNode` instance is normally passed to [`oak::run_event_loop`], to
/// allow repeated invocation of its `invoke()` method.
///
/// You can choose to implement this trait yourself, or use the convenient
/// `Dispatcher` created by the gRPC code generator.
///
/// [`oak::run_event_loop`]: ../../oak/fn.run_event_loop.html
pub trait ServerNode {
    /// Process a single gRPC method invocation.
    ///
    /// The method name is provided by `method` and the incoming serialized gRPC
    /// request is held in `req`.  Response messages should be written using
    /// `writer.write`, followed by `writer.close`.
    fn invoke(&mut self, method: &str, req: &[u8], writer: ChannelResponseWriter);
}

impl<T: ServerNode> crate::Node<Invocation> for T {
    /// Handle incoming gRPC events for an [`ServerNode`].
    ///
    /// Invoking the given `node`'s [`invoke`] method for each incoming request that
    /// arrives on the inbound channel as a serialized [`Invocation`] object,
    /// giving the [`invoke`] method the outbound channel for encapsulated responses
    /// to be written to.
    ///
    /// [`invoke`]: ServerNode::invoke
    fn handle_command(
        &mut self,
        invocation: Invocation,
    ) -> std::result::Result<(), crate::OakError> {
        // Read a single encapsulated request message from the read half.
        let req: GrpcRequest = invocation.request_receiver.receive()?;
        // Since we are expecting a single message, close the channel immediately.
        // This will change when we implement client streaming (#97).
        invocation.request_receiver.close()?;
        if !req.last {
            // TODO(#97): Implement client streaming.
            panic!("Support for streaming requests not yet implemented");
        }
        self.invoke(
            &req.method_name,
            req.get_req_msg().value.as_slice(),
            ChannelResponseWriter::new(invocation.response_sender),
        );
        Ok(())
    }
}

/// Encapsulate a protocol buffer message in a GrpcRequest wrapper using the
/// given method name.
pub fn encap_request<T: protobuf::Message>(req: T, method_name: &str) -> Option<GrpcRequest> {
    // Put the request in a GrpcRequest wrapper and serialize it.
    let mut grpc_req = GrpcRequest::new();
    grpc_req.set_method_name(method_name.to_string());
    let mut any = protobuf::well_known_types::Any::new();
    if let Err(e) = req.write_to_writer(&mut any.value) {
        warn!("failed to serialize gRPC request: {}", e);
        return None;
    };
    grpc_req.set_req_msg(any);
    grpc_req.set_last(true);
    Some(grpc_req)
}

/// Extract a protocol buffer message from a GrpcResponse wrapper.
/// Returns the message together with an indicator of whether this is the last
/// response.
pub fn decap_response<T: protobuf::Message>(mut grpc_rsp: GrpcResponse) -> Result<(T, bool)> {
    if grpc_rsp.get_status().get_code() != Code::OK.value() {
        return Err(grpc_rsp.take_status());
    }
    let rsp = protobuf::parse_from_bytes(&grpc_rsp.get_rsp_msg().value).map_err(|proto_err| {
        build_status(
            Code::INVALID_ARGUMENT,
            &format!("message parsing failed: {}", proto_err),
        )
    })?;
    Ok((rsp, grpc_rsp.get_last()))
}

/// Helper to inject a (single) gRPC request message via a notification channel,
/// in the same manner as the gRPC pseudo-Node does, and return a channel for
/// reading responses from.
pub fn invoke_grpc_method_stream<R>(
    method_name: &str,
    req: R,
    invocation_channel: &crate::io::Sender<Invocation>,
) -> Result<crate::io::Receiver<GrpcResponse>>
where
    R: protobuf::Message,
{
    // Create a new channel for request message delivery.
    let (req_sender, req_receiver) =
        crate::io::channel_create::<GrpcRequest>().expect("failed to create channel");

    // Put the request in a GrpcRequest wrapper and send it into the request
    // message channel.
    let req = encap_request(req, method_name).expect("failed to serialize GrpcRequest");
    req_sender.send(&req).expect("failed to write to channel");
    req_sender.close().expect("failed to close channel");

    // Create a new channel for responses to arrive on.
    let (rsp_sender, rsp_receiver) =
        crate::io::channel_create::<GrpcResponse>().expect("failed to create channel");

    // Build an Invocation holding the two channels and send it down the
    // specified channel.
    let invocation = Invocation {
        request_receiver: req_receiver.clone(),
        response_sender: rsp_sender.clone(),
    };
    invocation_channel
        .send(&invocation)
        .expect("failed to write invocation to channel");
    req_receiver.close().expect("failed to close channel");
    rsp_sender.close().expect("failed to close channel");

    Ok(rsp_receiver)
}

/// Helper to inject a (single) gRPC request message via a notification channel,
/// in the same manner as the gRPC pseudo-Node does, and collect a (single)
/// response.
pub fn invoke_grpc_method<R, Q>(
    method_name: &str,
    req: R,
    invocation_channel: &crate::io::Sender<Invocation>,
) -> Result<Q>
where
    R: protobuf::Message,
    Q: protobuf::Message,
{
    let rsp_receiver = invoke_grpc_method_stream(method_name, req, invocation_channel)?;
    // Read a single encapsulated response.
    let result = rsp_receiver.receive();
    rsp_receiver.close().expect("failed to close channel");
    let grpc_rsp = result.map_err(|status| {
        error!("failed to receive response: {:?}", status);
        build_status(
            Code::INTERNAL,
            &format!("failed to receive gRPC response: {:?}", status),
        )
    })?;
    let (rsp, _last) = decap_response(grpc_rsp)?;

    Ok(rsp)
}

/// Generic function that handles request deserialization and response
/// serialization (and sending down a channel) for a function that handles a
/// request/response pair.
///
/// Panics if [de-]serialization or channel operations fail.
pub fn handle_req_rsp<C, R, Q>(mut node_fn: C, req: &[u8], mut writer: ChannelResponseWriter)
where
    C: FnMut(R) -> Result<Q>,
    R: protobuf::Message,
    Q: protobuf::Message,
{
    let r: R = protobuf::parse_from_bytes(&req).expect("Failed to parse request protobuf message");
    let result = match node_fn(r) {
        Ok(rsp) => writer.write(&rsp, WriteMode::Close),
        Err(status) => writer.close(Err(status)),
    };
    if let Err(e) = result {
        panic!("Failed to process response: {:?}", e)
    }
}

/// Generic function that handles request deserialization and response
/// serialization (and sending down a channel) for a function that handles a
/// request and streams responses.
///
/// Panics if [de-]serialization or channel operations fail.
pub fn handle_req_stream<C, R>(mut node_fn: C, req: &[u8], writer: ChannelResponseWriter)
where
    C: FnMut(R, ChannelResponseWriter),
    R: protobuf::Message,
{
    let r: R = protobuf::parse_from_bytes(&req).expect("Failed to parse request protobuf message");
    node_fn(r, writer)
}

/// Generic function that handles request deserialization and response
/// serialization (and sending down a channel) for a function that handles a
/// stream of requests to produce a response.
///
/// Panics if [de-]serialization or channel operations fail.
pub fn handle_stream_rsp<C, R, Q>(mut node_fn: C, req: &[u8], mut writer: ChannelResponseWriter)
where
    C: FnMut(Vec<R>) -> Result<Q>,
    R: protobuf::Message,
    Q: protobuf::Message,
{
    // TODO(#97): better client-side streaming
    let rr: Vec<R> =
        vec![protobuf::parse_from_bytes(&req).expect("Failed to parse request protobuf message")];
    let result = match node_fn(rr) {
        Ok(rsp) => writer.write(&rsp, WriteMode::Close),
        Err(status) => writer.close(Err(status)),
    };
    if let Err(e) = result {
        panic!("Failed to process response: {:?}", e)
    }
}

/// Generic function that handles request deserialization and response
/// serialization (and sending down a channel) for a function that handles a
/// stream of requests to produce a stream of responses.
///
/// Panics if [de-]serialization or channel operations fail.
pub fn handle_stream_stream<C, R>(mut node_fn: C, req: &[u8], writer: ChannelResponseWriter)
where
    C: FnMut(Vec<R>, ChannelResponseWriter),
    R: protobuf::Message,
{
    // TODO(#97): better client-side streaming
    let rr: Vec<R> =
        vec![protobuf::parse_from_bytes(&req).expect("Failed to parse request protobuf message")];
    node_fn(rr, writer)
}
<|endoftext|>


<commit_before>//
// Copyright (c) Pirmin Kalberer. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//

use core::Config;
use toml;
use rustc_serialize::Decodable;
use std::collections::HashMap;

#[derive(Default)]
pub struct Layer {
    pub name: String,
    pub table_name: Option<String>,
    pub geometry_field: Option<String>,
    pub geometry_type: Option<String>,
    pub fid_field: Option<String>,
    pub query_limit: Option<u32>,
    pub query: Option<String>,
}

impl Layer {
    pub fn new(name: &str) -> Layer {
        Layer { name: String::from(name), ..Default::default() }
    }
    pub fn layers_from_config(config: &toml::Value) -> Result<Vec<Self>, String> {
        config.lookup("layer")
              .ok_or("Missing configuration entry [[tileset.layer]]".to_string())
              .and_then(|larr| larr.as_slice().ok_or("Array type for [[tileset.layer]] entry expected".to_string()))
              .and_then(|layers| {
                 Ok(layers.iter().map(|layer| Layer::from_config(layer).unwrap()).collect())
               })
    }
    /// Layer properties needed e.g. for metadata.json
    pub fn metadata(&self) -> HashMap<&str, &str> {
        //TODO: return Zoom-Level Array
        let mut metadata: HashMap<&str, &str> = HashMap::new();
        metadata.insert("id", &self.name);
        metadata.insert("name", &self.name);
        metadata.insert("description", "");
        metadata.insert("buffer-size", "0");
        metadata.insert("minzoom", "0");
        metadata.insert("maxzoom", "22");
        metadata.insert("srs", "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over");
        metadata
    }
}

impl Config<Layer> for Layer {
    fn from_config(layerval: &toml::Value) -> Result<Self, String> {
        let name = layerval.lookup("name")
                           .ok_or("Missing configuration entry name in [[tileset.layer]]".to_string())
                           .and_then(|val| val.as_str().ok_or("layer.name entry is not a string".to_string()))
                           .map(|v| v.to_string());
        let table_name =     layerval.lookup("table_name")
                                     .and_then(|val| val.as_str().map(|v| v.to_string()));
        let geometry_field = layerval.lookup("geometry_field")
                                     .and_then(|val| val.as_str().map(|v| v.to_string()));
        let geometry_type =  layerval.lookup("geometry_type")
                                     .and_then(|val| val.as_str().map(|v| v.to_string()));
        let fid_field =      layerval.lookup("fid_field")
                                     .and_then(|val| val.as_str().map(|v| v.to_string()));
        let query_limit =    layerval.lookup("query_limit")
                                     .and_then(|val| val.as_integer().map(|v| v as u32));
        let query =          layerval.lookup("query")
                                     .and_then(|val| val.as_str().map(|v| v.to_string()));
        name.and_then(|n|
            Ok(Layer { name:          n,
                   table_name:     table_name,
                   geometry_field: geometry_field,
                   geometry_type:  geometry_type,
                   fid_field:      fid_field,
                   query_limit:    query_limit,
                   query:          query,
            }))
    }

    fn gen_config() -> String {
        let toml = r#"
[[tileset]]
name = "points"

[[tileset.layer]]
name = "points"
table_name = "mytable"
geometry_field = "wkb_geometry"
geometry_type = "POINT"
#fid_field = "id"
#query = "SELECT name,wkb_geometry FROM mytable"
"#;
        toml.to_string()
    }

    fn gen_runtime_config(&self) -> String {
        let mut lines = vec!["\n[[tileset]]".to_string()];
        lines.push(format!(r#"name = "{}""#, self.name));
        lines.push("\n[[tileset.layer]]".to_string());
        lines.push(format!(r#"name = "{}""#, self.name));
        match self.table_name {
            Some(ref table_name)
                => lines.push(format!(r#"table_name = "{}""#, table_name)),
            _   => lines.push(r#"#table_name = "mytable""#.to_string())
        }
        match self.geometry_field {
            Some(ref geometry_field)
                => lines.push(format!("geometry_field = \"{}\"", geometry_field)),
            _   => lines.push("#geometry_field = \"wkb_geometry\"".to_string())
        }
        match self.geometry_type {
            Some(ref geometry_type)
                => lines.push(format!("geometry_type = \"{}\"", geometry_type)),
            _   => lines.push("#geometry_type = \"POINT\"".to_string())
        }
        match self.fid_field {
            Some(ref fid_field)
                => lines.push(format!("fid_field = \"{}\"", fid_field)),
            _   => lines.push("#fid_field = \"id\"".to_string())
        }
        match self.query_limit {
            Some(ref query_limit)
                => lines.push(format!("query_limit = {}", query_limit)),
            _   => {}
        }
        match self.query {
            Some(ref query)
                => lines.push(format!("query = \"{}\"", query)),
            _   => {
                let default_name = "mytable".to_string();
                let ref table_name = self.table_name.as_ref().unwrap_or(&default_name);
                let default_name = "wkb_geometry".to_string();
                let ref geometry_field = self.geometry_field.as_ref().unwrap_or(&default_name);
                lines.push(format!("#query = \"SELECT name,{} FROM {}\"", geometry_field, table_name))
            }
        }
        lines.join("\n") + "\n"
    }
}

#[cfg(test)]
#[derive(RustcDecodable, Debug)]
struct Layerlevel {
    pub minzoom: u8,
    pub maxzoom: u8,
    pub sql: String,
}

#[cfg(test)]
#[derive(RustcDecodable, Debug)]
struct LayerConfig {
    pub name: String,
    pub table_name: Option<String>,
    pub geometry_field: Option<String>,
    pub geometry_type: Option<String>,
    pub fid_field: Option<String>,
    pub query_limit: Option<u32>,
    pub query: Option<String>,
    pub level: Vec<Layerlevel>,
}

#[test]
fn test_toml_decode() {
    use core::parse_config;
    let toml = r#"
        [[tileset.layer]]
        name = "points"
        table_name = "ne_10m_populated_places"
        geometry_field = "wkb_geometry"
        geometry_type = "POINT"
        fid_field = "id"
        query_limit = 100
        query = "SELECT name,wkb_geometry FROM ne_10m_populated_places"
        [[tileset.layer.level]]
        minzoom = 10
        maxzoom = 14
        sql = "SELECT name,wkb_geometry FROM places_z10"

        [[tileset.layer]]
        name = "points2"

        [[tileset.layer]]
        table_name = "missing_name"
        "#;

    let tomlcfg = parse_config(toml.to_string(), "").unwrap();
    let layers = tomlcfg.lookup("tileset.layer").unwrap().as_slice().unwrap();

    // Layer config with zoom level dependent queries
    let ref layer = layers[0];
    let mut decoder = toml::Decoder::new(layer.clone());
    let cfg = LayerConfig::decode(&mut decoder).unwrap();
    println!("{:?}", cfg);
    assert_eq!(cfg.name, "points");
    assert_eq!(cfg.table_name, Some("ne_10m_populated_places".to_string()));
    assert_eq!(cfg.level.len(), 1);
    assert_eq!(cfg.level[0].minzoom, 10);
    assert_eq!(cfg.level[0].sql, "SELECT name,wkb_geometry FROM places_z10");

    // Minimal config
    let ref layer = layers[1];
    let mut decoder = toml::Decoder::new(layer.clone());
    let cfg = LayerConfig::decode(&mut decoder).unwrap();
    println!("{:?}", cfg);
    assert_eq!(cfg.name, "points2");
    assert_eq!(cfg.table_name, None);
    assert_eq!(cfg.level.len(), 0);

    // Invalid config
    let ref layer = layers[2];
    let mut decoder = toml::Decoder::new(layer.clone());
    let cfg = LayerConfig::decode(&mut decoder);
    assert_eq!(format!("{}", cfg.err().unwrap()),
        "expected a value of type `string` for the key `name`");
}

#[test]
fn test_layers_from_config() {
    use core::parse_config;
    let toml = r#"
        [[tileset]]
        name = "ne"

        [[tileset.layer]]
        name = "points"
        table_name = "ne_10m_populated_places"
        geometry_field = "wkb_geometry"
        geometry_type = "POINT"
        fid_field = "id"
        query_limit = 100
        query = "SELECT name,wkb_geometry FROM ne_10m_populated_places"

        [[tileset.layer]]
        name = "layer2"
        "#;

    let config = parse_config(toml.to_string(), "").unwrap();

    let tilesets = config.lookup("tileset").unwrap().as_slice().unwrap();
    let layers = Layer::layers_from_config(&tilesets[0]).unwrap();
    assert_eq!(layers.len(), 2);
    assert_eq!(layers[0].name, "points");
    assert_eq!(layers[0].table_name, Some("ne_10m_populated_places".to_string()));
    assert_eq!(layers[1].table_name, None);

    // errors
    let emptyconfig = parse_config("".to_string(), "").unwrap();
    let layers = Layer::layers_from_config(&emptyconfig);
    assert_eq!(layers.err(), Some("Missing configuration entry [[tileset.layer]]".to_string()));
}
<commit_msg>Use toml::Decoder for reading layer config<commit_after>//
// Copyright (c) Pirmin Kalberer. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//

use core::Config;
use toml;
use rustc_serialize::Decodable;
use std::collections::HashMap;

#[derive(Default, RustcDecodable, Debug)]
pub struct Layer {
    pub name: String,
    pub table_name: Option<String>,
    pub geometry_field: Option<String>,
    pub geometry_type: Option<String>,
    pub fid_field: Option<String>,
    pub query_limit: Option<u32>,
    pub query: Option<String>,
}

impl Layer {
    pub fn new(name: &str) -> Layer {
        Layer { name: String::from(name), ..Default::default() }
    }
    pub fn layers_from_config(config: &toml::Value) -> Result<Vec<Self>, String> {
        config.lookup("layer")
              .ok_or("Missing configuration entry [[tileset.layer]]".to_string())
              .and_then(|larr| larr.as_slice().ok_or("Array type for [[tileset.layer]] entry expected".to_string()))
              .and_then(|layers| {
                 Ok(layers.iter().map(|layer| Layer::from_config(layer).unwrap()).collect())
               })
    }
    /// Layer properties needed e.g. for metadata.json
    pub fn metadata(&self) -> HashMap<&str, &str> {
        //TODO: return Zoom-Level Array
        let mut metadata: HashMap<&str, &str> = HashMap::new();
        metadata.insert("id", &self.name);
        metadata.insert("name", &self.name);
        metadata.insert("description", "");
        metadata.insert("buffer-size", "0");
        metadata.insert("minzoom", "0");
        metadata.insert("maxzoom", "22");
        metadata.insert("srs", "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over");
        metadata
    }
}

impl Config<Layer> for Layer {
    fn from_config(layerval: &toml::Value) -> Result<Self, String> {
        let mut decoder = toml::Decoder::new(layerval.clone());
        let layer = Layer::decode(&mut decoder);
        layer.map_err(|e| format!("Error reading configuration - {}", e))
    }

    fn gen_config() -> String {
        let toml = r#"
[[tileset]]
name = "points"

[[tileset.layer]]
name = "points"
table_name = "mytable"
geometry_field = "wkb_geometry"
geometry_type = "POINT"
#fid_field = "id"
#query = "SELECT name,wkb_geometry FROM mytable"
"#;
        toml.to_string()
    }

    fn gen_runtime_config(&self) -> String {
        let mut lines = vec!["\n[[tileset]]".to_string()];
        lines.push(format!(r#"name = "{}""#, self.name));
        lines.push("\n[[tileset.layer]]".to_string());
        lines.push(format!(r#"name = "{}""#, self.name));
        match self.table_name {
            Some(ref table_name)
                => lines.push(format!(r#"table_name = "{}""#, table_name)),
            _   => lines.push(r#"#table_name = "mytable""#.to_string())
        }
        match self.geometry_field {
            Some(ref geometry_field)
                => lines.push(format!("geometry_field = \"{}\"", geometry_field)),
            _   => lines.push("#geometry_field = \"wkb_geometry\"".to_string())
        }
        match self.geometry_type {
            Some(ref geometry_type)
                => lines.push(format!("geometry_type = \"{}\"", geometry_type)),
            _   => lines.push("#geometry_type = \"POINT\"".to_string())
        }
        match self.fid_field {
            Some(ref fid_field)
                => lines.push(format!("fid_field = \"{}\"", fid_field)),
            _   => lines.push("#fid_field = \"id\"".to_string())
        }
        match self.query_limit {
            Some(ref query_limit)
                => lines.push(format!("query_limit = {}", query_limit)),
            _   => {}
        }
        match self.query {
            Some(ref query)
                => lines.push(format!("query = \"{}\"", query)),
            _   => {
                let default_name = "mytable".to_string();
                let ref table_name = self.table_name.as_ref().unwrap_or(&default_name);
                let default_name = "wkb_geometry".to_string();
                let ref geometry_field = self.geometry_field.as_ref().unwrap_or(&default_name);
                lines.push(format!("#query = \"SELECT name,{} FROM {}\"", geometry_field, table_name))
            }
        }
        lines.join("\n") + "\n"
    }
}

#[cfg(test)]
#[derive(RustcDecodable, Debug)]
struct Layerlevel {
    pub minzoom: u8,
    pub maxzoom: u8,
    pub sql: String,
}

#[cfg(test)]
#[derive(RustcDecodable, Debug)]
struct LayerConfig {
    pub name: String,
    pub table_name: Option<String>,
    pub geometry_field: Option<String>,
    pub geometry_type: Option<String>,
    pub fid_field: Option<String>,
    pub query_limit: Option<u32>,
    pub query: Option<String>,
    pub level: Vec<Layerlevel>,
}

#[test]
fn test_toml_decode() {
    use core::parse_config;
    let toml = r#"
        [[tileset.layer]]
        name = "points"
        table_name = "ne_10m_populated_places"
        geometry_field = "wkb_geometry"
        geometry_type = "POINT"
        fid_field = "id"
        query_limit = 100
        query = "SELECT name,wkb_geometry FROM ne_10m_populated_places"
        [[tileset.layer.level]]
        minzoom = 10
        maxzoom = 14
        sql = "SELECT name,wkb_geometry FROM places_z10"

        [[tileset.layer]]
        name = "points2"

        [[tileset.layer]]
        table_name = "missing_name"

        [[tileset.layer]]
        name = "points3"
        tabel_name = "spelling error"

        [[tileset.layer]]
        name = "points4"
        table_name = 0
        "#;

    let tomlcfg = parse_config(toml.to_string(), "").unwrap();
    let layers = tomlcfg.lookup("tileset.layer").unwrap().as_slice().unwrap();

    // Layer config with zoom level dependent queries
    let ref layer = layers[0];
    let mut decoder = toml::Decoder::new(layer.clone());
    let cfg = LayerConfig::decode(&mut decoder).unwrap();
    println!("{:?}", cfg);
    assert_eq!(cfg.name, "points");
    assert_eq!(cfg.table_name, Some("ne_10m_populated_places".to_string()));
    assert_eq!(cfg.level.len(), 1);
    assert_eq!(cfg.level[0].minzoom, 10);
    assert_eq!(cfg.level[0].sql, "SELECT name,wkb_geometry FROM places_z10");

    // Minimal config
    let ref layer = layers[1];
    let mut decoder = toml::Decoder::new(layer.clone());
    let cfg = LayerConfig::decode(&mut decoder).unwrap();
    println!("{:?}", cfg);
    assert_eq!(cfg.name, "points2");
    assert_eq!(cfg.table_name, None);
    assert_eq!(cfg.level.len(), 0);

    // Invalid config: missing required field
    let ref layer = layers[2];
    let mut decoder = toml::Decoder::new(layer.clone());
    let cfg = LayerConfig::decode(&mut decoder);
    println!("{:?}", cfg);
    assert_eq!(format!("{}", cfg.err().unwrap()),
        "expected a value of type `string` for the key `name`");

    // Invalid config: wrong field name
    let ref layer = layers[3];
    let mut decoder = toml::Decoder::new(layer.clone());
    let cfg = LayerConfig::decode(&mut decoder);
    println!("{:?}", cfg);
    // toml::Decoder ignores unknown keys!
    assert_eq!(cfg.err(), None);

    // Invalid config: wrong field type
    let ref layer = layers[4];
    let mut decoder = toml::Decoder::new(layer.clone());
    let cfg = LayerConfig::decode(&mut decoder);
    println!("{:?}", cfg);
    assert_eq!(format!("{}", cfg.err().unwrap()),
        "expected a value of type `string`, but found a value of type `integer` for the key `table_name`");
}

#[test]
fn test_layers_from_config() {
    use core::parse_config;
    let toml = r#"
        [[tileset]]
        name = "ne"

        [[tileset.layer]]
        name = "points"
        table_name = "ne_10m_populated_places"
        geometry_field = "wkb_geometry"
        geometry_type = "POINT"
        fid_field = "id"
        query_limit = 100
        query = "SELECT name,wkb_geometry FROM ne_10m_populated_places"

        [[tileset.layer]]
        name = "layer2"
        "#;

    let config = parse_config(toml.to_string(), "").unwrap();

    let tilesets = config.lookup("tileset").unwrap().as_slice().unwrap();
    let layers = Layer::layers_from_config(&tilesets[0]).unwrap();
    assert_eq!(layers.len(), 2);
    assert_eq!(layers[0].name, "points");
    assert_eq!(layers[0].table_name, Some("ne_10m_populated_places".to_string()));
    assert_eq!(layers[1].table_name, None);

    // errors
    let emptyconfig = parse_config("".to_string(), "").unwrap();
    let layers = Layer::layers_from_config(&emptyconfig);
    assert_eq!(layers.err(), Some("Missing configuration entry [[tileset.layer]]".to_string()));
}
<|endoftext|>


<commit_before>use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;

/// Cached size field used in generated code.
/// It is always equal to itself to simplify generated code.
/// (Generated code can use `#[derive(Eq)]`).
#[derive(Debug, Default)]
pub struct CachedSize {
    size: AtomicUsize,
}

impl CachedSize {
    pub fn get(&self) -> u32 {
        self.size.load(Ordering::Relaxed) as u32
    }

    pub fn set(&self, size: u32) {
        self.size.store(size as usize, Ordering::Relaxed)
    }
}

impl Clone for CachedSize {
    fn clone(&self) -> CachedSize {
        CachedSize {
            size: AtomicUsize::new(self.size.load(Ordering::Relaxed))
        }
    }
}

impl PartialEq<CachedSize> for CachedSize {
    fn eq(&self, _other: &CachedSize) -> bool {
        true
    }
}

impl Eq for CachedSize {}
<commit_msg>Implement Hash for CachedSize<commit_after>use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use std::hash::Hash;
use std::hash::Hasher;

/// Cached size field used in generated code.
/// It is always equal to itself to simplify generated code.
/// (Generated code can use `#[derive(Eq)]`).
#[derive(Debug, Default)]
pub struct CachedSize {
    size: AtomicUsize,
}

impl CachedSize {
    pub fn get(&self) -> u32 {
        self.size.load(Ordering::Relaxed) as u32
    }

    pub fn set(&self, size: u32) {
        self.size.store(size as usize, Ordering::Relaxed)
    }
}

impl Clone for CachedSize {
    fn clone(&self) -> CachedSize {
        CachedSize {
            size: AtomicUsize::new(self.size.load(Ordering::Relaxed))
        }
    }
}

impl PartialEq<CachedSize> for CachedSize {
    fn eq(&self, _other: &CachedSize) -> bool {
        true
    }
}

impl Eq for CachedSize {}

impl Hash for CachedSize {
    fn hash<H : Hasher>(&self, _state: &mut H) {
        // ignore cached size in cache computation
    }
}
<|endoftext|>


<commit_before>use crate::io::blocking::Blocking;
use crate::io::AsyncRead;

use std::io;
use std::pin::Pin;
use std::task::Context;
use std::task::Poll;

cfg_io_std! {
    /// A handle to the standard input stream of a process.
    ///
    /// The handle implements the [`AsyncRead`] trait, but beware that concurrent
    /// reads of `Stdin` must be executed with care.
    ///
    /// As an additional caveat, reading from the handle may block the calling
    /// future indefinitely if there is not enough data available. This makes this
    /// handle unsuitable for use in any circumstance where immediate reaction to
    /// available data is required, e.g. interactive use or when implementing a
    /// subprocess driven by requests on the standard input.
    ///
    /// Created by the [`stdin`] function.
    ///
    /// [`stdin`]: fn@stdin
    /// [`AsyncRead`]: trait@AsyncRead
    #[derive(Debug)]
    pub struct Stdin {
        std: Blocking<std::io::Stdin>,
    }

    /// Constructs a new handle to the standard input of the current process.
    ///
    /// The returned handle allows reading from standard input from the within the
    /// Tokio runtime.
    ///
    /// As an additional caveat, reading from the handle may block the calling
    /// future indefinitely if there is not enough data available. This makes this
    /// handle unsuitable for use in any circumstance where immediate reaction to
    /// available data is required, e.g. interactive use or when implementing a
    /// subprocess driven by requests on the standard input.
    pub fn stdin() -> Stdin {
        let std = io::stdin();
        Stdin {
            std: Blocking::new(std),
        }
    }
}

#[cfg(unix)]
impl std::os::unix::io::AsRawFd for Stdin {
    fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
        std::io::stdin().as_raw_fd()
    }
}

#[cfg(windows)]
impl std::os::windows::io::AsRawHandle for Stdin {
    fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
        std::io::stdin().as_raw_handle()
    }
}

impl AsyncRead for Stdin {
    fn poll_read(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut [u8],
    ) -> Poll<io::Result<usize>> {
        Pin::new(&mut self.std).poll_read(cx, buf)
    }
}
<commit_msg>io: rewrite stdin documentation (#2420)<commit_after>use crate::io::blocking::Blocking;
use crate::io::AsyncRead;

use std::io;
use std::pin::Pin;
use std::task::Context;
use std::task::Poll;

cfg_io_std! {
    /// A handle to the standard input stream of a process.
    ///
    /// The handle implements the [`AsyncRead`] trait, but beware that concurrent
    /// reads of `Stdin` must be executed with care.
    ///
    /// This handle is best used for non-interactive uses, such as when a file
    /// is piped into the application. For technical reasons, `stdin` is
    /// implemented by using an ordinary blocking read on a separate thread, and
    /// it is impossible to cancel that read. This can make shutdown of the
    /// runtime hang until the user presses enter.
    ///
    /// For interactive uses, it is recommended to spawn a thread dedicated to
    /// user input and use blocking IO directly in that thread.
    ///
    /// Created by the [`stdin`] function.
    ///
    /// [`stdin`]: fn@stdin
    /// [`AsyncRead`]: trait@AsyncRead
    #[derive(Debug)]
    pub struct Stdin {
        std: Blocking<std::io::Stdin>,
    }

    /// Constructs a new handle to the standard input of the current process.
    ///
    /// This handle is best used for non-interactive uses, such as when a file
    /// is piped into the application. For technical reasons, `stdin` is
    /// implemented by using an ordinary blocking read on a separate thread, and
    /// it is impossible to cancel that read. This can make shutdown of the
    /// runtime hang until the user presses enter.
    ///
    /// For interactive uses, it is recommended to spawn a thread dedicated to
    /// user input and use blocking IO directly in that thread.
    pub fn stdin() -> Stdin {
        let std = io::stdin();
        Stdin {
            std: Blocking::new(std),
        }
    }
}

#[cfg(unix)]
impl std::os::unix::io::AsRawFd for Stdin {
    fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
        std::io::stdin().as_raw_fd()
    }
}

#[cfg(windows)]
impl std::os::windows::io::AsRawHandle for Stdin {
    fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
        std::io::stdin().as_raw_handle()
    }
}

impl AsyncRead for Stdin {
    fn poll_read(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut [u8],
    ) -> Poll<io::Result<usize>> {
        Pin::new(&mut self.std).poll_read(cx, buf)
    }
}
<|endoftext|>