1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 //! This create implement the IPC proxy and stub for "example.calc.ipc.ICalcService"
17 
18 extern crate ipc_rust;
19 
20 mod access_token;
21 
22 use ipc_rust::{
23     IRemoteBroker, IRemoteObj, RemoteStub, IpcResult,
24     IpcStatusCode, RemoteObj, define_remote_object, FIRST_CALL_TRANSACTION,
25 };
26 use ipc_rust::{
27     MsgParcel, BorrowedMsgParcel,
28 };
29 use std::convert::{TryFrom, TryInto};
30 pub use access_token::init_access_token;
31 
32 /// add num1 + num2
add(num1: &i32, num2: &i32) -> i3233 pub fn add(num1: &i32, num2: &i32) -> i32 {
34     num1 + num2
35 }
36 
37 /// sub num1 + num2
sub(num1: &i32, num2: &i32) -> i3238 pub fn sub(num1: &i32, num2: &i32) -> i32 {
39     num1 - num2
40 }
41 
42 /// mul num1 + num2
mul(num1: &i32, num2: &i32) -> i3243 pub fn mul(num1: &i32, num2: &i32) -> i32 {
44     num1 * num2
45 }
46 
47 /// div num1 + num2
div(num1: &i32, num2: &i32) -> i3248 pub fn div(num1: &i32, num2: &i32) -> i32 {
49     match num2 {
50         0 => {
51             println!("Zero cannot be divided");
52             -1
53         },
54         _ => num1 / num2,
55     }
56 }
57 
58 /// SA ID for "example.calc.ipc.ICalcService"
59 pub const EXAMPLE_IPC_CALC_SERVICE_ID: i32 = 1118;
60 
61 /// Function code of ICalcService
62 pub enum ICalcCode {
63     /// add
64     CodeAdd = FIRST_CALL_TRANSACTION,
65     /// sub
66     CodeSub,
67     /// mul
68     CodeMul,
69     /// div
70     CodeDiv,
71 }
72 
73 impl TryFrom<u32> for ICalcCode {
74     type Error = IpcStatusCode;
try_from(code: u32) -> IpcResult<Self>75     fn try_from(code: u32) -> IpcResult<Self> {
76         match code {
77             _ if code == ICalcCode::CodeAdd as u32 => Ok(ICalcCode::CodeAdd),
78             _ if code == ICalcCode::CodeSub as u32 => Ok(ICalcCode::CodeSub),
79             _ if code == ICalcCode::CodeMul as u32 => Ok(ICalcCode::CodeMul),
80             _ if code == ICalcCode::CodeDiv as u32 => Ok(ICalcCode::CodeDiv),
81             _ => Err(IpcStatusCode::Failed),
82         }
83     }
84 }
85 
86 /// Function between proxy and stub of ICalcService
87 pub trait ICalc: IRemoteBroker {
88     /// Calc add num1 + num2
add(&self, num1: i32, num2: i32) -> IpcResult<i32>89     fn add(&self, num1: i32, num2: i32) -> IpcResult<i32>;
90     /// Calc sub num1 + num2
sub(&self, num1: i32, num2: i32) -> IpcResult<i32>91     fn sub(&self, num1: i32, num2: i32) -> IpcResult<i32>;
92     /// Calc mul num1 + num2
mul(&self, num1: i32, num2: i32) -> IpcResult<i32>93     fn mul(&self, num1: i32, num2: i32) -> IpcResult<i32>;
94     /// Calc div num1 + num2
div(&self, num1: i32, num2: i32) -> IpcResult<i32>95     fn div(&self, num1: i32, num2: i32) -> IpcResult<i32>;
96 }
97 
on_icalc_remote_request(stub: &dyn ICalc, code: u32, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> IpcResult<()>98 fn on_icalc_remote_request(stub: &dyn ICalc, code: u32, data: &BorrowedMsgParcel,
99     reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
100     match code.try_into()? {
101         ICalcCode::CodeAdd => {
102             let num1: i32 = data.read().expect("Failed to read num1 in addition operation");
103             let num2: i32 = data.read().expect("Failed to read num2 in addition operation");
104             let ret = stub.add(num1, num2)?;
105             reply.write(&ret)?;
106             Ok(())
107         }
108         ICalcCode::CodeSub => {
109             let num1: i32 = data.read().expect("Failed to read num1 in subtraction operation");
110             let num2: i32 = data.read().expect("Failed to read num1 in subtraction operation");
111             let ret = stub.sub(num1, num2)?;
112             reply.write(&ret)?;
113             Ok(())
114         }
115         ICalcCode::CodeMul => {
116             let num1: i32 = data.read().expect("Failed to read num1 in multiplication operation");
117             let num2: i32 = data.read().expect("Failed to read num1 in multiplication operation");
118             let ret = stub.mul(num1, num2)?;
119             reply.write(&ret)?;
120             Ok(())
121         }
122         ICalcCode::CodeDiv => {
123             let num1: i32 = data.read().expect("Failed to read num1 in division  operation");
124             let num2: i32 = data.read().expect("Failed to read num1 in division  operation");
125             let ret = stub.div(num1, num2)?;
126             reply.write(&ret)?;
127             Ok(())
128         }
129     }
130 }
131 
132 define_remote_object!(
133     ICalc["example.calc.ipc.ICalcService"] {
134         stub: CalcStub(on_icalc_remote_request),
135         proxy: CalcProxy,
136     }
137 );
138 
139 // Make RemoteStub<CalcStub> object can call ICalc function directly.
140 impl ICalc for RemoteStub<CalcStub> {
add(&self, num1: i32, num2: i32) -> IpcResult<i32>141     fn add (&self, num1: i32, num2: i32) -> IpcResult<i32> {
142         self.0.add(num1, num2)
143     }
sub(&self, num1: i32, num2: i32) -> IpcResult<i32>144     fn sub (&self, num1: i32, num2: i32) -> IpcResult<i32> {
145         self.0.sub(num1, num2)
146     }
mul(&self, num1: i32, num2: i32) -> IpcResult<i32>147     fn mul (&self, num1: i32, num2: i32) -> IpcResult<i32> {
148         self.0.mul(num1, num2)
149     }
div(&self, num1: i32, num2: i32) -> IpcResult<i32>150     fn div (&self, num1: i32, num2: i32) -> IpcResult<i32> {
151         self.0.div(num1, num2)
152     }
153 }
154 
155 impl ICalc for CalcProxy {
add(&self, num1: i32, num2: i32) -> IpcResult<i32>156     fn add(&self, num1: i32, num2: i32) -> IpcResult<i32> {
157         let mut data = MsgParcel::new().expect("MsgParcel should success");
158         data.write(&num1)?;
159         data.write(&num2)?;
160         let reply = self.remote.send_request(ICalcCode::CodeAdd as u32,
161             &data, false)?;
162         let ret: i32 = reply.read().expect("need reply i32");
163         Ok(ret)
164     }
sub(&self, num1: i32, num2: i32) -> IpcResult<i32>165     fn sub(&self, num1: i32, num2: i32) -> IpcResult<i32> {
166         let mut data = MsgParcel::new().expect("MsgParcel should success");
167         data.write(&num1)?;
168         data.write(&num2)?;
169         let reply = self.remote.send_request(ICalcCode::CodeSub as u32,
170             &data, false)?;
171         let ret: i32 = reply.read().expect("need reply i32");
172         Ok(ret)
173     }
mul(&self, num1: i32, num2: i32) -> IpcResult<i32>174     fn mul(&self, num1: i32, num2: i32) -> IpcResult<i32> {
175         let mut data = MsgParcel::new().expect("MsgParcel should success");
176         data.write(&num1)?;
177         data.write(&num2)?;
178         let reply = self.remote.send_request(ICalcCode::CodeMul as u32,
179             &data, false)?;
180         let ret: i32 = reply.read().expect("need reply i32");
181         Ok(ret)
182     }
div(&self, num1: i32, num2: i32) -> IpcResult<i32>183     fn div(&self, num1: i32, num2: i32) -> IpcResult<i32> {
184         let mut data = MsgParcel::new().expect("MsgParcel should success");
185         data.write(&num1)?;
186         data.write(&num2)?;
187         let reply = self.remote.send_request(ICalcCode::CodeDiv as u32,
188             &data, false)?;
189         let ret: i32 = reply.read().expect("need reply i32");
190         Ok(ret)
191     }
192 }