rust_macios/foundation/
ns_decimal.rs

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    /* Creating a Decimal from Another Decimal
24     */
25
26    /// Creating a Decimal from Another Decimal
27    pub fn NSDecimalCopy(destination: *mut NSDecimal, source: *const NSDecimal);
28
29    /* Converting Between Decimals and Strings
30     */
31
32    /// Returns a string representation of the decimal value appropriate for the specified locale.
33    pub fn NSDecimalString(dcm: *const NSDecimal, locale: NSLocale) -> NSString;
34
35    /// Compacts the decimal structure for efficiency.
36    pub fn NSDecimalCompact(number: *mut NSDecimal);
37
38    /// Adds two decimal values.
39    pub fn NSDecimalAdd(
40        result: *mut NSDecimal,
41        leftOperand: *const NSDecimal,
42        rightOperand: *const NSDecimal,
43        roundingMode: NSRoundingMode,
44    ) -> NSCalculationError;
45
46    /// Subtracts one decimal value from another.
47    pub fn NSDecimalSubtract(
48        result: *mut NSDecimal,
49        leftOperand: *const NSDecimal,
50        rightOperand: *const NSDecimal,
51        roundingMode: NSRoundingMode,
52    ) -> NSCalculationError;
53
54    /// Subtracts one decimal value from another.
55    pub fn NSDecimalMultiply(
56        result: *mut NSDecimal,
57        leftOperand: *const NSDecimal,
58        rightOperand: *const NSDecimal,
59        roundingMode: NSRoundingMode,
60    ) -> NSCalculationError;
61
62    /// Multiplies two decimal numbers together.
63    pub fn NSDecimalDivide(
64        result: *mut NSDecimal,
65        leftOperand: *const NSDecimal,
66        rightOperand: *const NSDecimal,
67        roundingMode: NSRoundingMode,
68    ) -> NSCalculationError;
69
70    /// Multiplies a decimal by the specified power of 10.
71    pub fn NSDecimalPower(
72        result: *mut NSDecimal,
73        number: *const NSDecimal,
74        power: c_short,
75        roundingMode: NSRoundingMode,
76    ) -> NSCalculationError;
77
78    /// Rounds off the decimal value.
79    pub fn NSDecimalRound(
80        result: *mut NSDecimal,
81        number: *const NSDecimal,
82        scale: c_short,
83        roundingMode: NSRoundingMode,
84    ) -> NSCalculationError;
85
86    /// Raises the decimal value to the specified power.
87    pub fn NSDecimalMultiplyByPowerOf10(
88        result: *mut NSDecimal,
89        number: *const NSDecimal,
90        power: c_short,
91        roundingMode: NSRoundingMode,
92    ) -> NSCalculationError;
93
94    /// Normalizes the internal format of two decimal numbers to simplify later operations.
95    pub fn NSDecimalNormalize(
96        result: *mut NSDecimal,
97        number1: *const NSDecimal,
98        number2: *const NSDecimal,
99    );
100
101    /* Comparing Decimals
102     */
103
104    /// Compares two decimal values.
105    pub fn NSDecimalCompare(
106        leftOperand: *const NSDecimal,
107        rightOperand: *const NSDecimal,
108    ) -> NSComparisonResult;
109}
110
111object! {
112    /// An object for representing and performing arithmetic on base-10 numbers.
113    unsafe pub struct NSDecimalNumber;
114}
115
116impl INSValue for NSDecimalNumber {}
117
118impl INSNumber for NSDecimalNumber {}
119
120#[interface_impl(NSNumber)]
121impl NSDecimalNumber {
122    /* Creating a Decimal Number
123     */
124
125    /// Creates and returns a decimal number equivalent to a given decimal structure.
126    #[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    /// Creates and returns a decimal number equivalent to the number specified by the arguments.
140    #[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    /// Creates a decimal number whose value is equivalent to that in a given numeric string.
160    #[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    /// Creates a decimal number whose value is equivalent to that in a given numeric string, interpreted using a given locale.
169    #[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    /// A decimal number equivalent to the number 1.0.
180    #[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    /// A decimal number equivalent to the number 0.0.
189    #[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    /// A decimal number that specifies no number.
198    #[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    /* Initializing a Decimal Number
207     */
208
209    /// Initializes a decimal number to represent a given decimal.
210    #[method]
211    pub fn init_with_decimal(&mut self, decimal: NSDecimalNumber) {
212        unsafe { msg_send![self.m_self(), initWithDecimal: decimal] }
213    }
214
215    /// Initializes a decimal number using the given mantissa, exponent, and sign.
216    #[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    /// Initializes a decimal number so that its value is equivalent to that in a given numeric string.
231    #[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    /// Initializes a decimal number so that its value is equivalent to that in a given numeric string, interpreted using a given locale.
240    #[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    /* Performing Arithmetic
250     */
251
252    /// Adds this number to another given number.
253    #[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    /// Subtracts another given number from this one.
267    #[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    /// Multiplies the number by another given number.
281    #[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    /// Divides the number by another given number.
295    #[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    /// Raises the number to a given power.
309    #[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    /// Multiplies the number by 10 raised to the given power.
323    #[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    /// Adds this number to another given number using the specified behavior.
337    #[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    /// Subtracts this a given number from this one using the specified behavior.
356    #[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    /// Multiplies this number by another given number using the specified behavior.
375    #[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    /// Divides this number by another given number using the specified behavior.
394    #[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    /// Raises the number to a given power using the specified behavior.
413    #[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    /// Multiplies the number by 10 raised to the given power using the specified behavior.
432    #[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    /* Rounding Off
451     */
452
453    /// Returns a rounded version of the decimal number using the specified rounding behavior.
454    #[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    /* Managing Behavior
471     */
472
473    /// The way arithmetic methods round off and handle error conditions.
474    #[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    /// Sets the way arithmetic methods round off and handle error conditions.
483    #[property]
484    pub fn set_default_behavior(behavior: Arc<dyn PNSDecimalNumberBehaviors>) {
485        unsafe { msg_send![Self::m_class(), setDefaultBehavior: behavior] }
486    }
487
488    /// A C string containing the Objective-C type for the data contained in the decimal number object.
489    #[property]
490    pub fn objc_type(&self) -> *const c_char {
491        unsafe { msg_send![self.m_self(), objCType] }
492    }
493
494    /* Getting Maximum and Minimum Possible Values
495     */
496
497    /// Returns the largest possible value of a decimal number.
498    #[property]
499    pub fn maximum_decimal_number() -> NSDecimalNumber {
500        unsafe { NSDecimalNumber::from_id(msg_send![Self::m_class(), maximumDecimalNumber]) }
501    }
502
503    /// Returns the smallest possible value of a decimal number.
504    #[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}