| 118 | } |
| 119 | |
| 120 | fn handle_calculate(&self, logid: i32, w: Work) -> thrift::Result<i32> { |
| 121 | println!("handling calculate: l:{}, w:{:?}", logid, w); |
| 122 | |
| 123 | let res = if let Some(ref op) = w.op { |
| 124 | if w.num1.is_none() || w.num2.is_none() { |
| 125 | Err(InvalidOperation { |
| 126 | what_op: Some(op.into()), |
| 127 | why: Some("no operands specified".to_owned()), |
| 128 | }) |
| 129 | } else { |
| 130 | // so that I don't have to call unwrap() multiple times below |
| 131 | let num1 = w.num1.as_ref().expect("operands checked"); |
| 132 | let num2 = w.num2.as_ref().expect("operands checked"); |
| 133 | |
| 134 | match *op { |
| 135 | Operation::ADD => Ok(num1 + num2), |
| 136 | Operation::SUBTRACT => Ok(num1 - num2), |
| 137 | Operation::MULTIPLY => Ok(num1 * num2), |
| 138 | Operation::DIVIDE => { |
| 139 | if *num2 == 0 { |
| 140 | Err(InvalidOperation { |
| 141 | what_op: Some(op.into()), |
| 142 | why: Some("divide by 0".to_owned()), |
| 143 | }) |
| 144 | } else { |
| 145 | Ok(num1 / num2) |
| 146 | } |
| 147 | } |
| 148 | _ => { |
| 149 | let op_val: i32 = op.into(); |
| 150 | Err(InvalidOperation { |
| 151 | what_op: Some(op_val), |
| 152 | why: Some(format!("unsupported operation type '{}'", op_val)), |
| 153 | }) |
| 154 | } |
| 155 | } |
| 156 | } |
| 157 | } else { |
| 158 | Err(InvalidOperation::new( |
| 159 | None, |
| 160 | "no operation specified".to_owned(), |
| 161 | )) |
| 162 | }; |
| 163 | |
| 164 | // if the operation was successful log it |
| 165 | if let Ok(ref v) = res { |
| 166 | let mut log = self.log.lock().unwrap(); |
| 167 | log.insert(logid, SharedStruct::new(logid, format!("{}", v))); |
| 168 | } |
| 169 | |
| 170 | // the try! macro automatically maps errors |
| 171 | // but, since we aren't using that here we have to map errors manually |
| 172 | // |
| 173 | // exception structs defined in the IDL have an auto-generated |
| 174 | // impl of From::from |
| 175 | res.map_err(From::from) |
| 176 | } |
| 177 | |