Skip to content

Commit ade704c

Browse files
committed
Add as_i32 feature to use i32 for Number type
1 parent 1340772 commit ade704c

File tree

3 files changed

+74
-5
lines changed

3 files changed

+74
-5
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ jobs:
2020
- name: Test Rust
2121
run: cargo test
2222

23+
- name: Test Rust (as_i32)
24+
run: cargo test --features as_i32
25+
2326
rustfmt:
2427
runs-on: ubuntu-latest
2528
steps:

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ authors = ["Paul Colomiets <[email protected]>"]
1515
edition = "2018"
1616
rust-version = "1.61"
1717

18+
[features]
19+
default = []
20+
# Use 32-bit integers instead of 64-bit for the Number type
21+
as_i32 = []
22+
1823
[dependencies]
1924
combine = "4.6.6"
2025
thiserror = "2"

src/common.rs

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,19 @@ pub struct Directive<'a, T: Text<'a>> {
4545
/// This represents integer number
4646
///
4747
/// But since there is no definition on limit of number in spec
48-
/// (only in implemetation), we do a trick similar to the one
48+
/// (only in implementation), we do a trick similar to the one
4949
/// in `serde_json`: encapsulate value in new-type, allowing type
5050
/// to be extended later.
5151
#[derive(Debug, Clone, PartialEq)]
52-
// we use i64 as a reference implementation: graphql-js thinks even 32bit
53-
// integers is enough. We might consider lift this limit later though
52+
// we use i64 as a reference implementation by default.
53+
#[cfg(not(feature = "as_i32"))]
5454
pub struct Number(pub(crate) i64);
5555

56+
#[derive(Debug, Clone, PartialEq)]
57+
// Use i32 when the as_i32 feature is enabled
58+
#[cfg(feature = "as_i32")]
59+
pub struct Number(pub(crate) i32);
60+
5661
#[derive(Debug, Clone, PartialEq)]
5762
pub enum Value<'a, T: Text<'a>> {
5863
Variable(T::Value),
@@ -96,13 +101,43 @@ pub enum Type<'a, T: Text<'a>> {
96101
impl Number {
97102
/// Returns a number as i64 if it fits the type
98103
pub fn as_i64(&self) -> Option<i64> {
99-
Some(self.0)
104+
#[cfg(not(feature = "as_i32"))]
105+
{
106+
Some(self.0)
107+
}
108+
#[cfg(feature = "as_i32")]
109+
{
110+
Some(self.0 as i64)
111+
}
112+
}
113+
114+
/// Returns a number as i32 if it fits the type
115+
pub fn as_i32(&self) -> Option<i32> {
116+
#[cfg(not(feature = "as_i32"))]
117+
{
118+
if self.0 >= i32::MIN as i64 && self.0 <= i32::MAX as i64 {
119+
Some(self.0 as i32)
120+
} else {
121+
None
122+
}
123+
}
124+
#[cfg(feature = "as_i32")]
125+
{
126+
Some(self.0)
127+
}
100128
}
101129
}
102130

103131
impl From<i32> for Number {
104132
fn from(i: i32) -> Self {
105-
Number(i as i64)
133+
#[cfg(not(feature = "as_i32"))]
134+
{
135+
Number(i as i64)
136+
}
137+
#[cfg(feature = "as_i32")]
138+
{
139+
Number(i)
140+
}
106141
}
107142
}
108143

@@ -418,6 +453,32 @@ mod tests {
418453
assert_eq!(Number::from(i32::MAX).as_i64(), Some(i32::MAX as i64));
419454
}
420455

456+
#[test]
457+
fn number_as_i32_conversion() {
458+
// Test values that fit in i32
459+
assert_eq!(Number::from(1).as_i32(), Some(1));
460+
assert_eq!(Number::from(584).as_i32(), Some(584));
461+
assert_eq!(Number::from(i32::MIN).as_i32(), Some(i32::MIN));
462+
assert_eq!(Number::from(i32::MAX).as_i32(), Some(i32::MAX));
463+
464+
#[cfg(not(feature = "as_i32"))]
465+
{
466+
// Test values that don't fit in i32 (only when using i64 internally)
467+
let too_large = Number(i32::MAX as i64 + 1);
468+
assert_eq!(too_large.as_i32(), None);
469+
470+
let too_small = Number(i32::MIN as i64 - 1);
471+
assert_eq!(too_small.as_i32(), None);
472+
}
473+
474+
#[cfg(feature = "as_i32")]
475+
{
476+
// When using i32 internally, all values will fit in i32
477+
assert_eq!(Number(0).as_i32(), Some(0));
478+
assert_eq!(Number(-1).as_i32(), Some(-1));
479+
}
480+
}
481+
421482
#[test]
422483
fn unquote_unicode_string() {
423484
// basic tests

0 commit comments

Comments
 (0)