1 // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
2 // Licensed under the MIT License:
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to deal
6 // in the Software without restriction, including without limitation the rights
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 // copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 // THE SOFTWARE.
21 
22 use crate::any_pointer;
23 use crate::MessageSize;
24 use crate::capability::{Params, Promise, Request, RemotePromise, Results};
25 
26 pub trait ResponseHook {
get<'a>(&'a self) -> crate::Result<any_pointer::Reader<'a>>27     fn get<'a>(&'a self) -> crate::Result<any_pointer::Reader<'a>>;
28 }
29 
30 pub trait RequestHook {
get<'a>(&'a mut self) -> any_pointer::Builder<'a>31     fn get<'a>(&'a mut self) -> any_pointer::Builder<'a>;
get_brand(&self) -> usize32     fn get_brand(&self) -> usize;
send<'a>(self: Box<Self>) -> RemotePromise<any_pointer::Owned>33     fn send<'a>(self: Box<Self>) -> RemotePromise<any_pointer::Owned>;
tail_send(self: Box<Self>) -> Option<(u32, crate::capability::Promise<(), crate::Error>, Box<dyn PipelineHook>)>34     fn tail_send(self: Box<Self>)
35                  -> Option<(u32, crate::capability::Promise<(), crate::Error>, Box<dyn PipelineHook>)>;
36 }
37 
38 pub trait ClientHook {
add_ref(&self) -> Box<dyn ClientHook>39     fn add_ref(&self) -> Box<dyn ClientHook>;
new_call(&self, interface_id: u64, method_id: u16, size_hint: Option<MessageSize>) -> Request<any_pointer::Owned, any_pointer::Owned>40     fn new_call(&self,
41                 interface_id: u64,
42                 method_id: u16,
43                 size_hint: Option<MessageSize>)
44                 -> Request<any_pointer::Owned, any_pointer::Owned>;
45 
call(&self, interface_id: u64, method_id: u16, params: Box<dyn ParamsHook>, results: Box<dyn ResultsHook>) -> crate::capability::Promise<(), crate::Error>46     fn call(&self, interface_id: u64, method_id: u16,
47             params: Box<dyn ParamsHook>, results: Box<dyn ResultsHook>)
48             -> crate::capability::Promise<(), crate::Error>;
49 
get_brand(&self) -> usize50     fn get_brand(&self) -> usize;
get_ptr(&self) -> usize51     fn get_ptr(&self) -> usize;
52 
53     /// If this ClientHook is a promise that has already resolved, returns the inner, resolved version
54     /// of the capability.  The caller may permanently replace this client with the resolved one if
55     /// desired.  Returns null if the client isn't a promise or hasn't resolved yet -- use
56     /// `whenMoreResolved()` to distinguish between them.
get_resolved(&self) -> Option<Box<dyn ClientHook>>57     fn get_resolved(&self) -> Option<Box<dyn ClientHook>>;
58 
59 
60     /// If this client is a settled reference (not a promise), return nullptr.  Otherwise, return a
61     /// promise that eventually resolves to a new client that is closer to being the final, settled
62     /// client (i.e. the value eventually returned by `getResolved()`).  Calling this repeatedly
63     /// should eventually produce a settled client.
when_more_resolved(&self) -> Option<crate::capability::Promise<Box<dyn ClientHook>, crate::Error>>64     fn when_more_resolved(&self) -> Option<crate::capability::Promise<Box<dyn ClientHook>, crate::Error>>;
65 
66     /// Repeatedly calls whenMoreResolved() until it returns nullptr.
67     #[cfg(feature = "rpc")]
when_resolved(&self) -> Promise<(), crate::Error>68     fn when_resolved(&self) -> Promise<(), crate::Error> {
69         use futures::Future;
70 
71         match self.when_more_resolved() {
72             Some(promise) => {
73                 Promise::from_future(promise.and_then(|resolution| {
74                     resolution.when_resolved()
75                 }))
76             }
77             None => {
78                 Promise::ok(())
79             }
80         }
81     }
82 }
83 
84 impl Clone for Box<dyn ClientHook> {
clone(&self) -> Box<dyn ClientHook>85     fn clone(&self) -> Box<dyn ClientHook> {
86         self.add_ref()
87     }
88 }
89 
90 pub trait ServerHook: 'static {
new_client(server: Box<dyn crate::capability::Server>) -> crate::capability::Client91     fn new_client(server: Box<dyn crate::capability::Server>) -> crate::capability::Client;
92 }
93 
94 pub trait ResultsHook {
get<'a>(&'a mut self) -> crate::Result<any_pointer::Builder<'a>>95     fn get<'a>(&'a mut self) -> crate::Result<any_pointer::Builder<'a>>;
allow_cancellation(&self)96     fn allow_cancellation(&self);
tail_call(self: Box<Self>, request: Box<dyn RequestHook>) -> Promise<(), crate::Error>97     fn tail_call(self: Box<Self>, request: Box<dyn RequestHook>) -> Promise<(), crate::Error>;
direct_tail_call(self: Box<Self>, request: Box<dyn RequestHook>) -> (crate::capability::Promise<(), crate::Error>, Box<dyn PipelineHook>)98     fn direct_tail_call(self: Box<Self>, request: Box<dyn RequestHook>) ->
99         (crate::capability::Promise<(), crate::Error>, Box<dyn PipelineHook>);
100 }
101 
102 pub trait ParamsHook {
get<'a>(&'a self) -> crate::Result<crate::any_pointer::Reader<'a>>103     fn get<'a>(&'a self) -> crate::Result<crate::any_pointer::Reader<'a>>;
104 }
105 
106 // Where should this live?
internal_get_typed_params<T>(typeless: Params<any_pointer::Owned>) -> Params<T>107 pub fn internal_get_typed_params<T>(typeless: Params<any_pointer::Owned>) -> Params<T> {
108     Params { hook: typeless.hook, marker: ::std::marker::PhantomData }
109 }
110 
internal_get_typed_results<T>(typeless: Results<any_pointer::Owned>) -> Results<T>111 pub fn internal_get_typed_results<T>(typeless: Results<any_pointer::Owned>) -> Results<T> {
112     Results { hook: typeless.hook, marker: ::std::marker::PhantomData }
113 }
114 
internal_get_untyped_results<T>(typeful: Results<T>) -> Results<any_pointer::Owned>115 pub fn internal_get_untyped_results<T>(typeful: Results<T>) -> Results<any_pointer::Owned> {
116     Results { hook: typeful.hook, marker: ::std::marker::PhantomData }
117 }
118 
119 pub trait PipelineHook {
add_ref(&self) -> Box<dyn PipelineHook>120     fn add_ref(&self) -> Box<dyn PipelineHook>;
get_pipelined_cap(&self, ops: &[PipelineOp]) -> Box<dyn ClientHook>121     fn get_pipelined_cap(&self, ops: &[PipelineOp]) -> Box<dyn ClientHook>;
122 
123     /// Version of get_pipelined_cap() passing the array by move. May avoid a copy in some cases.
124     /// Default implementation just calls the other version.
get_pipelined_cap_move(&self, ops: Vec<PipelineOp>) -> Box<dyn ClientHook>125     fn get_pipelined_cap_move(&self, ops: Vec<PipelineOp>) -> Box<dyn ClientHook> {
126         self.get_pipelined_cap(&ops)
127     }
128 }
129 
130 impl Clone for Box<dyn PipelineHook> {
clone(&self) -> Box<dyn PipelineHook>131     fn clone(&self) -> Box<dyn PipelineHook> {
132         self.add_ref()
133     }
134 }
135 
136 #[derive(Clone, Copy)]
137 pub enum PipelineOp {
138     Noop,
139     GetPointerField(u16),
140 }
141