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 18extern crate ipc_rust; 19 20mod access_token; 21 22use ipc_rust::{ 23 IRemoteBroker, IRemoteObj, RemoteStub, IpcResult, 24 IpcStatusCode, RemoteObj, define_remote_object, FIRST_CALL_TRANSACTION, 25}; 26use ipc_rust::{ 27 MsgParcel, BorrowedMsgParcel, 28}; 29use std::convert::{TryFrom, TryInto}; 30pub use access_token::init_access_token; 31 32/// add num1 + num2 33pub fn add(num1: &i32, num2: &i32) -> i32 { 34 num1 + num2 35} 36 37/// sub num1 + num2 38pub fn sub(num1: &i32, num2: &i32) -> i32 { 39 num1 - num2 40} 41 42/// mul num1 + num2 43pub fn mul(num1: &i32, num2: &i32) -> i32 { 44 num1 * num2 45} 46 47/// div num1 + num2 48pub 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" 59pub const EXAMPLE_IPC_CALC_SERVICE_ID: i32 = 1118; 60 61/// Function code of ICalcService 62pub enum ICalcCode { 63 /// add 64 CodeAdd = FIRST_CALL_TRANSACTION, 65 /// sub 66 CodeSub, 67 /// mul 68 CodeMul, 69 /// div 70 CodeDiv, 71} 72 73impl TryFrom<u32> for ICalcCode { 74 type Error = IpcStatusCode; 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 87pub trait ICalc: IRemoteBroker { 88 /// Calc add num1 + num2 89 fn add(&self, num1: i32, num2: i32) -> IpcResult<i32>; 90 /// Calc sub num1 + num2 91 fn sub(&self, num1: i32, num2: i32) -> IpcResult<i32>; 92 /// Calc mul num1 + num2 93 fn mul(&self, num1: i32, num2: i32) -> IpcResult<i32>; 94 /// Calc div num1 + num2 95 fn div(&self, num1: i32, num2: i32) -> IpcResult<i32>; 96} 97 98fn 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 132define_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. 140impl ICalc for RemoteStub<CalcStub> { 141 fn add (&self, num1: i32, num2: i32) -> IpcResult<i32> { 142 self.0.add(num1, num2) 143 } 144 fn sub (&self, num1: i32, num2: i32) -> IpcResult<i32> { 145 self.0.sub(num1, num2) 146 } 147 fn mul (&self, num1: i32, num2: i32) -> IpcResult<i32> { 148 self.0.mul(num1, num2) 149 } 150 fn div (&self, num1: i32, num2: i32) -> IpcResult<i32> { 151 self.0.div(num1, num2) 152 } 153} 154 155impl ICalc for CalcProxy { 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 } 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 } 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 } 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}