alox_48/rb_types/
fixnum.rs1use crate::{FromPrimitive, NumCast, ToPrimitive};
8
9#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
11pub struct Fixnum(i32);
12
13impl Fixnum {
14 pub fn from_le_bytes(is_negative: bool, le_bytes: &[u8]) -> Option<Self> {
18 let (is_negative, le_bytes) = super::canonicalize_le_bytes_ref(is_negative, le_bytes);
19 (le_bytes.len() <= size_of::<i32>())
20 .then(|| {
21 let value = i32::from_le_bytes(super::to_array_with_default(le_bytes));
22 let value = if is_negative {
23 value.wrapping_neg()
24 } else {
25 value
26 };
27 (value.is_negative() == is_negative)
28 .then(|| FromPrimitive::from_i32(value))
29 .flatten()
30 })
31 .flatten()
32 }
33}
34
35impl From<i8> for Fixnum {
36 fn from(value: i8) -> Self {
37 Self(value.into())
38 }
39}
40
41impl From<u8> for Fixnum {
42 fn from(value: u8) -> Self {
43 Self(value.into())
44 }
45}
46
47impl From<i16> for Fixnum {
48 fn from(value: i16) -> Self {
49 Self(value.into())
50 }
51}
52
53impl From<u16> for Fixnum {
54 fn from(value: u16) -> Self {
55 Self(value.into())
56 }
57}
58
59impl From<Fixnum> for i32 {
60 fn from(value: Fixnum) -> Self {
61 value.0
62 }
63}
64
65impl From<Fixnum> for i64 {
66 fn from(value: Fixnum) -> Self {
67 value.0.into()
68 }
69}
70
71impl From<Fixnum> for i128 {
72 fn from(value: Fixnum) -> Self {
73 value.0.into()
74 }
75}
76
77impl From<Fixnum> for num_bigint::BigInt {
78 fn from(value: Fixnum) -> Self {
79 value.0.into()
80 }
81}
82
83impl FromPrimitive for Fixnum {
84 fn from_i64(n: i64) -> Option<Self> {
85 if (-(1 << 30)..1 << 30).contains(&n) {
86 Some(Self(n as i32))
87 } else {
88 None
89 }
90 }
91
92 fn from_u64(n: u64) -> Option<Self> {
93 n.to_i64().and_then(Self::from_i64)
94 }
95}
96
97impl ToPrimitive for Fixnum {
98 fn to_i64(&self) -> Option<i64> {
99 self.0.to_i64()
100 }
101
102 fn to_u64(&self) -> Option<u64> {
103 self.0.to_u64()
104 }
105}
106
107impl NumCast for Fixnum {
108 fn from<T: ToPrimitive>(n: T) -> Option<Self> {
109 n.to_i32().and_then(FromPrimitive::from_i32)
110 }
111}
112
113macro_rules! try_from_impl {
114 ($($from:ty => $to:ty),* $(,)?) => {
115 $(impl TryFrom<$from> for $to {
116 type Error = $from;
117 fn try_from(value: $from) -> Result<Self, Self::Error> {
118 NumCast::from(value).ok_or(value)
119 }
120 })*
121 };
122}
123
124try_from_impl! {
125 i32 => Fixnum,
126 u32 => Fixnum,
127 i64 => Fixnum,
128 u64 => Fixnum,
129 i128 => Fixnum,
130 u128 => Fixnum,
131 isize => Fixnum,
132 usize => Fixnum,
133 Fixnum => i8,
134 Fixnum => u8,
135 Fixnum => i16,
136 Fixnum => u16,
137 Fixnum => u32,
138 Fixnum => u64,
139 Fixnum => u128,
140 Fixnum => isize,
141 Fixnum => usize,
142}
143
144impl num_bigint::ToBigInt for Fixnum {
145 fn to_bigint(&self) -> Option<num_bigint::BigInt> {
146 self.0.to_bigint()
147 }
148}
149
150impl num_bigint::ToBigUint for Fixnum {
151 fn to_biguint(&self) -> Option<num_bigint::BigUint> {
152 self.0.to_biguint()
153 }
154}
155
156impl std::fmt::Debug for Fixnum {
157 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
158 self.0.fmt(f)
159 }
160}
161
162impl std::fmt::Display for Fixnum {
163 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164 self.0.fmt(f)
165 }
166}