1use std::{
2 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign},
3 os::raw::c_float,
4 sync::Arc,
5};
6
7use libc::{c_char, c_double, c_int, c_long, c_short, c_uint, c_ulong, c_ulonglong, c_ushort};
8use objc::{msg_send, sel, sel_impl};
9
10use crate::{
11 foundation::{INSLocale, INSNumber, INSString, NSComparisonResult, NSLocale, NSString},
12 object,
13 objective_c_runtime::{macros::interface_impl, traits::FromId, INSValue},
14};
15
16use super::{
17 ns_decimal_number_behaviors::PNSDecimalNumberBehaviors, NSCalculationError, NSDecimal,
18 NSRoundingMode,
19};
20
21#[link(name = "Foundation", kind = "framework")]
22extern "C" {
23 pub fn NSDecimalCopy(destination: *mut NSDecimal, source: *const NSDecimal);
28
29 pub fn NSDecimalString(dcm: *const NSDecimal, locale: NSLocale) -> NSString;
34
35 pub fn NSDecimalCompact(number: *mut NSDecimal);
37
38 pub fn NSDecimalAdd(
40 result: *mut NSDecimal,
41 leftOperand: *const NSDecimal,
42 rightOperand: *const NSDecimal,
43 roundingMode: NSRoundingMode,
44 ) -> NSCalculationError;
45
46 pub fn NSDecimalSubtract(
48 result: *mut NSDecimal,
49 leftOperand: *const NSDecimal,
50 rightOperand: *const NSDecimal,
51 roundingMode: NSRoundingMode,
52 ) -> NSCalculationError;
53
54 pub fn NSDecimalMultiply(
56 result: *mut NSDecimal,
57 leftOperand: *const NSDecimal,
58 rightOperand: *const NSDecimal,
59 roundingMode: NSRoundingMode,
60 ) -> NSCalculationError;
61
62 pub fn NSDecimalDivide(
64 result: *mut NSDecimal,
65 leftOperand: *const NSDecimal,
66 rightOperand: *const NSDecimal,
67 roundingMode: NSRoundingMode,
68 ) -> NSCalculationError;
69
70 pub fn NSDecimalPower(
72 result: *mut NSDecimal,
73 number: *const NSDecimal,
74 power: c_short,
75 roundingMode: NSRoundingMode,
76 ) -> NSCalculationError;
77
78 pub fn NSDecimalRound(
80 result: *mut NSDecimal,
81 number: *const NSDecimal,
82 scale: c_short,
83 roundingMode: NSRoundingMode,
84 ) -> NSCalculationError;
85
86 pub fn NSDecimalMultiplyByPowerOf10(
88 result: *mut NSDecimal,
89 number: *const NSDecimal,
90 power: c_short,
91 roundingMode: NSRoundingMode,
92 ) -> NSCalculationError;
93
94 pub fn NSDecimalNormalize(
96 result: *mut NSDecimal,
97 number1: *const NSDecimal,
98 number2: *const NSDecimal,
99 );
100
101 pub fn NSDecimalCompare(
106 leftOperand: *const NSDecimal,
107 rightOperand: *const NSDecimal,
108 ) -> NSComparisonResult;
109}
110
111object! {
112 unsafe pub struct NSDecimalNumber;
114}
115
116impl INSValue for NSDecimalNumber {}
117
118impl INSNumber for NSDecimalNumber {}
119
120#[interface_impl(NSNumber)]
121impl NSDecimalNumber {
122 #[method]
127 pub fn decimal_number_with_decimal(decimal: NSDecimalNumber) -> Self
128 where
129 Self: Sized + FromId,
130 {
131 unsafe {
132 Self::from_id(msg_send![
133 Self::m_class(),
134 decimalNumberWithDecimal: decimal
135 ])
136 }
137 }
138
139 #[method]
141 pub fn decimal_number_with_mantissa(
142 mantissa: c_ulonglong,
143 exponent: c_short,
144 is_negative: bool,
145 ) -> Self
146 where
147 Self: Sized + FromId,
148 {
149 unsafe {
150 Self::from_id(msg_send![
151 Self::m_class(),
152 decimalNumberWithMantissa: mantissa
153 exponent: exponent
154 isNegative: is_negative
155 ])
156 }
157 }
158
159 #[method]
161 pub fn decimal_number_with_string(string: NSString) -> Self
162 where
163 Self: Sized + FromId,
164 {
165 unsafe { Self::from_id(msg_send![Self::m_class(), decimalNumberWithString: string]) }
166 }
167
168 #[method]
170 pub fn decimal_number_with_string_locale(string: NSString, locale: NSLocale) -> Self
171 where
172 Self: Sized + FromId,
173 {
174 unsafe {
175 Self::from_id(msg_send![Self::m_class(), decimalNumberWithString:string locale:locale])
176 }
177 }
178
179 #[property]
181 pub fn one() -> Self
182 where
183 Self: Sized + 'static + FromId,
184 {
185 unsafe { Self::from_id(msg_send![Self::m_class(), one]) }
186 }
187
188 #[property]
190 pub fn zero() -> Self
191 where
192 Self: Sized + 'static + FromId,
193 {
194 unsafe { Self::from_id(msg_send![Self::m_class(), zero]) }
195 }
196
197 #[property]
199 pub fn not_a_number() -> Self
200 where
201 Self: Sized + 'static + FromId,
202 {
203 unsafe { Self::from_id(msg_send![Self::m_class(), notANumber]) }
204 }
205
206 #[method]
211 pub fn init_with_decimal(&mut self, decimal: NSDecimalNumber) {
212 unsafe { msg_send![self.m_self(), initWithDecimal: decimal] }
213 }
214
215 #[method]
217 pub fn init_with_mantissa_exponent_is_negative(
218 &mut self,
219 mantissa: c_ulonglong,
220 exponent: c_short,
221 is_negative: bool,
222 ) {
223 unsafe {
224 msg_send![self.m_self(), initWithMantissa: mantissa
225 exponent: exponent
226 isNegative: is_negative]
227 }
228 }
229
230 #[method]
232 pub fn init_with_string<S>(&mut self, string: S)
233 where
234 S: INSString,
235 {
236 unsafe { msg_send![self.m_self(), initWithString: string] }
237 }
238
239 #[method]
241 pub fn init_with_string_locale<S, L>(&mut self, string: S, locale: L)
242 where
243 S: INSString,
244 L: INSLocale,
245 {
246 unsafe { msg_send![self.m_self(), initWithString: string locale: locale] }
247 }
248
249 #[method]
254 pub fn decimal_number_by_adding(&self, decimal_number: Self) -> Self
255 where
256 Self: Sized + FromId,
257 {
258 unsafe {
259 Self::from_id(msg_send![
260 self.m_self(),
261 decimalNumberByAdding: decimal_number
262 ])
263 }
264 }
265
266 #[method]
268 pub fn decimal_number_by_subtracting(&self, decimal_number: Self) -> Self
269 where
270 Self: Sized + FromId,
271 {
272 unsafe {
273 Self::from_id(msg_send![
274 self.m_self(),
275 decimalNumberBySubtracting: decimal_number
276 ])
277 }
278 }
279
280 #[method]
282 pub fn decimal_number_by_multiplying_by(&self, decimal_number: Self) -> Self
283 where
284 Self: Sized + FromId,
285 {
286 unsafe {
287 Self::from_id(msg_send![
288 self.m_self(),
289 decimalNumberByMultiplyingBy: decimal_number
290 ])
291 }
292 }
293
294 #[method]
296 pub fn decimal_number_by_dividing_by(&self, decimal_number: Self) -> Self
297 where
298 Self: Sized + FromId,
299 {
300 unsafe {
301 Self::from_id(msg_send![
302 self.m_self(),
303 decimalNumberByDividingBy: decimal_number
304 ])
305 }
306 }
307
308 #[method]
310 pub fn decimal_number_by_raising_to_power(&self, power: c_uint) -> Self
311 where
312 Self: Sized + FromId,
313 {
314 unsafe {
315 Self::from_id(msg_send![
316 self.m_self(),
317 decimalNumberByRaisingToPower: power
318 ])
319 }
320 }
321
322 #[method]
324 pub fn decimal_number_by_multiplying_by_power_of_10(&self, power: c_short) -> Self
325 where
326 Self: Sized + FromId,
327 {
328 unsafe {
329 Self::from_id(msg_send![
330 self.m_self(),
331 decimalNumberByMultiplyingByPowerOf10: power
332 ])
333 }
334 }
335
336 #[method]
338 pub fn decimal_number_by_adding_with_behavior(
339 &self,
340 decimal_number: &Self,
341 with_behavior: Arc<dyn PNSDecimalNumberBehaviors>,
342 ) -> Self
343 where
344 Self: Sized + FromId,
345 {
346 unsafe {
347 Self::from_id(msg_send![
348 self.m_self(),
349 decimalNumberByAdding: decimal_number
350 withBehavior: with_behavior
351 ])
352 }
353 }
354
355 #[method]
357 pub fn decimal_number_by_subtracting_with_behavior(
358 &self,
359 decimal_number: &Self,
360 with_behavior: Arc<dyn PNSDecimalNumberBehaviors>,
361 ) -> Self
362 where
363 Self: Sized + FromId,
364 {
365 unsafe {
366 Self::from_id(msg_send![
367 self.m_self(),
368 decimalNumberBySubtracting: decimal_number
369 withBehavior: with_behavior
370 ])
371 }
372 }
373
374 #[method]
376 pub fn decimal_number_by_multiplying_by_with_behavior(
377 &self,
378 decimal_number: &Self,
379 with_behavior: Arc<dyn PNSDecimalNumberBehaviors>,
380 ) -> Self
381 where
382 Self: Sized + FromId,
383 {
384 unsafe {
385 Self::from_id(msg_send![
386 self.m_self(),
387 decimalNumberByMultiplyingBy: decimal_number
388 withBehavior: with_behavior
389 ])
390 }
391 }
392
393 #[method]
395 pub fn decimal_number_by_dividing_by_with_behavior(
396 &self,
397 decimal_number: &Self,
398 with_behavior: Arc<dyn PNSDecimalNumberBehaviors>,
399 ) -> Self
400 where
401 Self: Sized + FromId,
402 {
403 unsafe {
404 Self::from_id(msg_send![
405 self.m_self(),
406 decimalNumberByDividingBy: decimal_number
407 withBehavior: with_behavior
408 ])
409 }
410 }
411
412 #[method]
414 pub fn decimal_number_by_raising_to_power_with_behavior(
415 &self,
416 power: c_uint,
417 with_behavior: Arc<dyn PNSDecimalNumberBehaviors>,
418 ) -> Self
419 where
420 Self: Sized + FromId,
421 {
422 unsafe {
423 Self::from_id(msg_send![
424 self.m_self(),
425 decimalNumberByRaisingToPower: power
426 withBehavior: with_behavior
427 ])
428 }
429 }
430
431 #[method]
433 pub fn decimal_number_by_multiplying_by_power_of10_with_behavior(
434 &self,
435 power: c_short,
436 with_behavior: Arc<dyn PNSDecimalNumberBehaviors>,
437 ) -> Self
438 where
439 Self: Sized + FromId,
440 {
441 unsafe {
442 Self::from_id(msg_send![
443 self.m_self(),
444 decimalNumberByMultiplyingByPowerOf10: power
445 withBehavior: with_behavior
446 ])
447 }
448 }
449
450 #[method]
455 pub fn decimal_number_by_rounding_according_to_behavior(
456 &self,
457 behavior: Arc<dyn PNSDecimalNumberBehaviors>,
458 ) -> Self
459 where
460 Self: Sized + FromId,
461 {
462 unsafe {
463 Self::from_id(msg_send![
464 self.m_self(),
465 decimalNumberByRoundingAccordingToBehavior: behavior
466 ])
467 }
468 }
469
470 #[property]
475 pub fn default_behavior() -> Arc<dyn PNSDecimalNumberBehaviors> {
476 unsafe {
477 let behavior = msg_send![Self::m_class(), defaultBehavior];
478 Arc::from_raw(behavior)
479 }
480 }
481
482 #[property]
484 pub fn set_default_behavior(behavior: Arc<dyn PNSDecimalNumberBehaviors>) {
485 unsafe { msg_send![Self::m_class(), setDefaultBehavior: behavior] }
486 }
487
488 #[property]
490 pub fn objc_type(&self) -> *const c_char {
491 unsafe { msg_send![self.m_self(), objCType] }
492 }
493
494 #[property]
499 pub fn maximum_decimal_number() -> NSDecimalNumber {
500 unsafe { NSDecimalNumber::from_id(msg_send![Self::m_class(), maximumDecimalNumber]) }
501 }
502
503 #[property]
505 pub fn minimum_decimal_number() -> NSDecimalNumber {
506 unsafe { NSDecimalNumber::from_id(msg_send![Self::m_class(), minimumDecimalNumber]) }
507 }
508}
509
510impl From<c_uint> for NSDecimalNumber {
511 fn from(value: c_uint) -> Self {
512 NSDecimalNumber::m_number_with_unsigned_int(value)
513 }
514}
515
516impl From<c_int> for NSDecimalNumber {
517 fn from(value: c_int) -> Self {
518 NSDecimalNumber::m_number_with_int(value)
519 }
520}
521
522impl From<c_short> for NSDecimalNumber {
523 fn from(value: c_short) -> Self {
524 NSDecimalNumber::m_number_with_short(value)
525 }
526}
527
528impl From<c_ushort> for NSDecimalNumber {
529 fn from(value: c_ushort) -> Self {
530 NSDecimalNumber::m_number_with_unsigned_short(value)
531 }
532}
533
534impl From<c_long> for NSDecimalNumber {
535 fn from(value: c_long) -> Self {
536 NSDecimalNumber::m_number_with_long(value)
537 }
538}
539
540impl From<c_ulong> for NSDecimalNumber {
541 fn from(value: c_ulong) -> Self {
542 NSDecimalNumber::m_number_with_unsigned_long(value)
543 }
544}
545
546impl From<c_float> for NSDecimalNumber {
547 fn from(value: c_float) -> Self {
548 NSDecimalNumber::m_number_with_float(value)
549 }
550}
551
552impl From<c_double> for NSDecimalNumber {
553 fn from(value: c_double) -> Self {
554 NSDecimalNumber::m_number_with_double(value)
555 }
556}
557
558impl<S> From<S> for NSDecimalNumber
559where
560 S: Into<NSString>,
561{
562 fn from(value: S) -> Self {
563 NSDecimalNumber::m_decimal_number_with_string(value.into())
564 }
565}
566
567impl<T> Add<T> for NSDecimalNumber
568where
569 T: Into<NSDecimalNumber>,
570{
571 type Output = NSDecimalNumber;
572
573 fn add(self, other: T) -> Self::Output {
574 self.m_decimal_number_by_adding(other.into())
575 }
576}
577
578impl<T> AddAssign<T> for NSDecimalNumber
579where
580 T: Into<NSDecimalNumber>,
581{
582 fn add_assign(&mut self, other: T) {
583 *self = self.clone().add(other.into());
584 }
585}
586
587impl<T> Sub<T> for NSDecimalNumber
588where
589 T: Into<NSDecimalNumber>,
590{
591 type Output = NSDecimalNumber;
592
593 fn sub(self, other: T) -> Self::Output {
594 self.m_decimal_number_by_subtracting(other.into())
595 }
596}
597
598impl<T> SubAssign<T> for NSDecimalNumber
599where
600 T: Into<NSDecimalNumber>,
601{
602 fn sub_assign(&mut self, other: T) {
603 *self = self.clone().sub(other.into());
604 }
605}
606
607impl<T> Mul<T> for NSDecimalNumber
608where
609 T: Into<NSDecimalNumber>,
610{
611 type Output = NSDecimalNumber;
612
613 fn mul(self, other: T) -> Self::Output {
614 self.m_decimal_number_by_multiplying_by(other.into())
615 }
616}
617
618impl<T> MulAssign<T> for NSDecimalNumber
619where
620 T: Into<NSDecimalNumber>,
621{
622 fn mul_assign(&mut self, other: T) {
623 *self = self.clone().mul(other.into());
624 }
625}
626
627impl<T> Div<T> for NSDecimalNumber
628where
629 T: Into<NSDecimalNumber>,
630{
631 type Output = NSDecimalNumber;
632
633 fn div(self, other: T) -> Self::Output {
634 self.m_decimal_number_by_dividing_by(other.into())
635 }
636}
637
638impl<T> DivAssign<T> for NSDecimalNumber
639where
640 T: Into<NSDecimalNumber>,
641{
642 fn div_assign(&mut self, other: T) {
643 *self = self.clone().div(other.into());
644 }
645}
646
647impl Add<NSDecimalNumber> for f64 {
648 type Output = NSDecimalNumber;
649
650 fn add(self, other: NSDecimalNumber) -> Self::Output {
651 other.add(self)
652 }
653}