xsd_types/value/decimal/integer/
non_positive_integer.rs

1use std::{
2	borrow::Borrow,
3	fmt,
4	ops::{Add, Div, Mul, Sub},
5	str::FromStr,
6};
7
8use num_bigint::{BigInt, TryFromBigIntError};
9use num_traits::{Signed, Zero};
10
11use crate::{
12	impl_integer_arithmetic,
13	lexical::{self, LexicalFormOf},
14	Datatype, Integer, NonPositiveIntegerDatatype, ParseXsd, XsdValue,
15};
16
17use super::Sign;
18
19#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
20pub struct NonPositiveInteger(BigInt);
21
22impl NonPositiveInteger {
23	/// Create a new non positive integer from a `BigInt`.
24	///
25	/// # Safety
26	///
27	/// The input number must be non positive.
28	pub unsafe fn new_unchecked(n: BigInt) -> Self {
29		Self(n)
30	}
31
32	/// Creates a non positive integer from its unsigned big endian bytes
33	/// representation.
34	pub fn from_bytes_be(bytes: &[u8]) -> Self {
35		Self(BigInt::from_bytes_be(Sign::Minus, bytes))
36	}
37
38	/// Creates a non positive integer from its unsigned little endian bytes
39	/// representation.
40	pub fn from_bytes_le(bytes: &[u8]) -> Self {
41		Self(BigInt::from_bytes_le(Sign::Minus, bytes))
42	}
43
44	/// Creates a non positive integer from its signed big endian bytes
45	/// representation.
46	///
47	/// # Safety
48	///
49	/// The represented number must be non positive.
50	pub unsafe fn from_signed_bytes_be_unchecked(bytes: &[u8]) -> Self {
51		Self(BigInt::from_signed_bytes_be(bytes))
52	}
53
54	/// Creates a non positive integer from its signed little endian bytes
55	/// representation.
56	///
57	/// # Safety
58	///
59	/// The represented number must be non positive.
60	pub unsafe fn from_signed_bytes_le_unchecked(bytes: &[u8]) -> Self {
61		Self(BigInt::from_signed_bytes_le(bytes))
62	}
63
64	pub fn from_signed_bytes_be(bytes: &[u8]) -> Result<Self, IntegerIsPositive> {
65		Integer::from_signed_bytes_be(bytes).try_into()
66	}
67
68	pub fn from_signed_bytes_le(bytes: &[u8]) -> Result<Self, IntegerIsPositive> {
69		Integer::from_signed_bytes_le(bytes).try_into()
70	}
71
72	#[inline(always)]
73	pub fn into_big_int(self) -> BigInt {
74		self.0
75	}
76
77	#[inline(always)]
78	pub fn zero() -> Self {
79		Self(BigInt::zero())
80	}
81
82	#[inline(always)]
83	pub fn is_zero(&self) -> bool {
84		self.0.is_zero()
85	}
86
87	#[inline(always)]
88	fn non_positive_integer_type(&self) -> NonPositiveIntegerDatatype {
89		if self.0 > BigInt::zero() {
90			NonPositiveIntegerDatatype::NegativeInteger
91		} else {
92			NonPositiveIntegerDatatype::NonPositiveInteger
93		}
94	}
95
96	/// Returns a lexical representation of this non positive integer.
97	#[inline(always)]
98	pub fn lexical_representation(&self) -> lexical::NonPositiveIntegerBuf {
99		unsafe {
100			// This is safe because the `Display::fmt` method matches the
101			// XSD lexical representation.
102			lexical::NonPositiveIntegerBuf::new_unchecked(format!("{}", self))
103		}
104	}
105
106	pub fn to_bytes_be(&self) -> (Sign, Vec<u8>) {
107		self.0.to_bytes_be()
108	}
109
110	pub fn to_bytes_le(&self) -> (Sign, Vec<u8>) {
111		self.0.to_bytes_le()
112	}
113
114	pub fn to_signed_bytes_be(&self) -> Vec<u8> {
115		self.0.to_signed_bytes_be()
116	}
117
118	pub fn to_signed_bytes_le(&self) -> Vec<u8> {
119		self.0.to_signed_bytes_le()
120	}
121}
122
123impl XsdValue for NonPositiveInteger {
124	#[inline(always)]
125	fn datatype(&self) -> Datatype {
126		self.non_positive_integer_type().into()
127	}
128}
129
130impl ParseXsd for NonPositiveInteger {
131	type LexicalForm = lexical::NonPositiveInteger;
132}
133
134impl LexicalFormOf<NonPositiveInteger> for lexical::NonPositiveInteger {
135	type ValueError = std::convert::Infallible;
136
137	fn try_as_value(&self) -> Result<NonPositiveInteger, Self::ValueError> {
138		Ok(self.value())
139	}
140}
141
142impl From<NonPositiveInteger> for BigInt {
143	fn from(value: NonPositiveInteger) -> Self {
144		value.0
145	}
146}
147
148impl<'a> From<&'a lexical::NonPositiveInteger> for NonPositiveInteger {
149	#[inline(always)]
150	fn from(value: &'a lexical::NonPositiveInteger) -> Self {
151		Self(value.as_str().parse().unwrap())
152	}
153}
154
155impl From<lexical::NonPositiveIntegerBuf> for NonPositiveInteger {
156	#[inline(always)]
157	fn from(value: lexical::NonPositiveIntegerBuf) -> Self {
158		value.as_non_positive_integer().into()
159	}
160}
161
162impl FromStr for NonPositiveInteger {
163	type Err = lexical::InvalidNonPositiveInteger;
164
165	#[inline(always)]
166	fn from_str(s: &str) -> Result<Self, Self::Err> {
167		let l = lexical::NonPositiveInteger::new(s)?;
168		Ok(l.into())
169	}
170}
171
172impl fmt::Display for NonPositiveInteger {
173	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174		self.0.fmt(f)
175	}
176}
177
178impl AsRef<BigInt> for NonPositiveInteger {
179	#[inline(always)]
180	fn as_ref(&self) -> &BigInt {
181		&self.0
182	}
183}
184
185impl Borrow<BigInt> for NonPositiveInteger {
186	#[inline(always)]
187	fn borrow(&self) -> &BigInt {
188		&self.0
189	}
190}
191
192impl_integer_arithmetic!(
193	for NonPositiveInteger where r ( !r.is_positive() ) {
194		Integer [.0],
195		NonPositiveInteger [.0],
196		NegativeInteger [.0],
197		super::NonNegativeInteger [.into_big_int()],
198		super::PositiveInteger [.into_big_int()],
199		i8,
200		i16,
201		i32,
202		i64,
203		isize,
204		u8,
205		u16,
206		u32,
207		u64,
208		usize
209	}
210);
211
212#[derive(Debug, thiserror::Error)]
213#[error("integer out of supported bounds: {0}")]
214pub struct NonPositiveIntegerOutOfTargetBounds(pub NonPositiveInteger);
215
216macro_rules! try_into {
217	{ $( $ty:ty ),* } => {
218		$(
219			impl TryFrom<NonPositiveInteger> for $ty {
220				type Error = NonPositiveIntegerOutOfTargetBounds;
221
222				fn try_from(value: NonPositiveInteger) -> Result<Self, Self::Error> {
223					value.0.try_into().map_err(|e: TryFromBigIntError<BigInt>| NonPositiveIntegerOutOfTargetBounds(NonPositiveInteger(e.into_original())))
224				}
225			}
226		)*
227	};
228}
229
230try_into!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
231
232#[derive(Debug, thiserror::Error)]
233#[error("integer {0} is negative")]
234pub struct IntegerIsPositive(Integer);
235
236impl TryFrom<Integer> for NonPositiveInteger {
237	type Error = IntegerIsPositive;
238
239	fn try_from(value: Integer) -> Result<Self, Self::Error> {
240		if value.is_positive() {
241			Err(IntegerIsPositive(value))
242		} else {
243			Ok(Self(value.into()))
244		}
245	}
246}
247
248#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
249pub struct NegativeInteger(BigInt);
250
251impl NegativeInteger {
252	/// Creates a new negative integer from the given `BigInt`.
253	///
254	/// # Safety
255	///
256	/// The input value *must* but a negative integer.
257	pub unsafe fn new_unchecked(n: BigInt) -> Self {
258		Self(n)
259	}
260
261	/// Creates a negative integer from its unsigned big endian bytes
262	/// representation.
263	///
264	/// # Safety
265	///
266	/// The represented number must be negative.
267	pub unsafe fn from_bytes_be_unchecked(bytes: &[u8]) -> Self {
268		Self(BigInt::from_bytes_be(Sign::Minus, bytes))
269	}
270
271	/// Creates a negative integer from its unsigned little endian bytes
272	/// representation.
273	///
274	/// # Safety
275	///
276	/// The represented number must be negative.
277	pub unsafe fn from_bytes_le_unchecked(bytes: &[u8]) -> Self {
278		Self(BigInt::from_bytes_le(Sign::Minus, bytes))
279	}
280
281	/// Creates a negative integer from its signed big endian bytes
282	/// representation.
283	///
284	/// # Safety
285	///
286	/// The represented number must be negative.
287	pub unsafe fn from_signed_bytes_be_unchecked(bytes: &[u8]) -> Self {
288		Self(BigInt::from_signed_bytes_be(bytes))
289	}
290
291	/// Creates a negative integer from its signed little endian bytes
292	/// representation.
293	///
294	/// # Safety
295	///
296	/// The represented number must be negative.
297	pub unsafe fn from_signed_bytes_le_unchecked(bytes: &[u8]) -> Self {
298		Self(BigInt::from_signed_bytes_le(bytes))
299	}
300
301	pub fn into_big_int(self) -> BigInt {
302		self.0
303	}
304
305	pub fn is_minus_one(&self) -> bool {
306		matches!(i8::try_from(&self.0), Ok(-1))
307	}
308
309	pub fn to_bytes_be(&self) -> (Sign, Vec<u8>) {
310		self.0.to_bytes_be()
311	}
312
313	pub fn to_bytes_le(&self) -> (Sign, Vec<u8>) {
314		self.0.to_bytes_le()
315	}
316
317	pub fn to_signed_bytes_be(&self) -> Vec<u8> {
318		self.0.to_signed_bytes_be()
319	}
320
321	pub fn to_signed_bytes_le(&self) -> Vec<u8> {
322		self.0.to_signed_bytes_le()
323	}
324}
325
326impl XsdValue for NegativeInteger {
327	fn datatype(&self) -> Datatype {
328		NonPositiveIntegerDatatype::NegativeInteger.into()
329	}
330}
331
332impl ParseXsd for NegativeInteger {
333	type LexicalForm = lexical::NegativeInteger;
334}
335
336impl LexicalFormOf<NegativeInteger> for lexical::NegativeInteger {
337	type ValueError = std::convert::Infallible;
338
339	fn try_as_value(&self) -> Result<NegativeInteger, Self::ValueError> {
340		Ok(self.value())
341	}
342}
343
344impl fmt::Display for NegativeInteger {
345	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
346		self.0.fmt(f)
347	}
348}
349
350impl From<NegativeInteger> for BigInt {
351	fn from(value: NegativeInteger) -> Self {
352		value.into_big_int()
353	}
354}
355
356impl_integer_arithmetic!(
357	for NegativeInteger where r ( r.is_negative() ) {
358		Integer [.0],
359		NonPositiveInteger [.0],
360		NegativeInteger [.0],
361		super::NonNegativeInteger [.into_big_int()],
362		super::PositiveInteger [.into_big_int()],
363		i8,
364		i16,
365		i32,
366		i64,
367		isize,
368		u8,
369		u16,
370		u32,
371		u64,
372		usize
373	}
374);