summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBratSinot <bratsinot@gmail.com>2022-07-25 19:37:44 +0200
committerBratSinot <bratsinot@gmail.com>2022-09-06 12:11:03 +0200
commit6ef2ad4a61692c509b89243aab560e5eaffae6fa (patch)
treea23d7bc52321bc67b0365a93c11fed629cfd6bd8
parentd655c66ff41b75b6cc20a9176d5f1ef4268deece (diff)
Fix FIXME in de.rs and value.rs.
-rw-r--r--src/de.rs89
-rw-r--r--src/value.rs27
-rw-r--r--tests/integer_range.rs10
3 files changed, 87 insertions, 39 deletions
diff --git a/src/de.rs b/src/de.rs
index 2b4834e..4794ec4 100644
--- a/src/de.rs
+++ b/src/de.rs
@@ -1,13 +1,38 @@
use std::collections::VecDeque;
+use std::convert::TryInto;
use std::iter::Enumerate;
use serde::de;
use crate::config::Config;
-use crate::error::{ConfigError, Result};
+use crate::error::{ConfigError, Result, Unexpected};
use crate::map::Map;
use crate::value::{Table, Value, ValueKind};
+macro_rules! try_convert_number {
+ (signed, $self:expr, $size:literal) => {{
+ let num = $self.into_int()?;
+ num.try_into().map_err(|_| {
+ ConfigError::invalid_type(
+ None,
+ Unexpected::I64(num),
+ concat!("an signed ", $size, " bit integer"),
+ )
+ })?
+ }};
+
+ (unsigned, $self:expr, $size:literal) => {{
+ let num = $self.into_uint()?;
+ num.try_into().map_err(|_| {
+ ConfigError::invalid_type(
+ None,
+ Unexpected::U64(num),
+ concat!("an unsigned ", $size, " bit integer"),
+ )
+ })?
+ }};
+}
+
impl<'de> de::Deserializer<'de> for Value {
type Error = ConfigError;
@@ -38,49 +63,50 @@ impl<'de> de::Deserializer<'de> for Value {
#[inline]
fn deserialize_i8<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- // FIXME: This should *fail* if the value does not fit in the requets integer type
- visitor.visit_i8(self.into_int()? as i8)
+ let num = try_convert_number!(signed, self, "8");
+ visitor.visit_i8(num)
}
#[inline]
fn deserialize_i16<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- // FIXME: This should *fail* if the value does not fit in the requets integer type
- visitor.visit_i16(self.into_int()? as i16)
+ let num = try_convert_number!(signed, self, "16");
+ visitor.visit_i16(num)
}
#[inline]
fn deserialize_i32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- // FIXME: This should *fail* if the value does not fit in the requets integer type
- visitor.visit_i32(self.into_int()? as i32)
+ let num = try_convert_number!(signed, self, "32");
+ visitor.visit_i32(num)
}
#[inline]
fn deserialize_i64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- visitor.visit_i64(self.into_int()?)
+ let num = try_convert_number!(signed, self, "64");
+ visitor.visit_i64(num)
}
#[inline]
fn deserialize_u8<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- // FIXME: This should *fail* if the value does not fit in the requets integer type
- visitor.visit_u8(self.into_uint()? as u8)
+ let num = try_convert_number!(unsigned, self, "8");
+ visitor.visit_u8(num)
}
#[inline]
fn deserialize_u16<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- // FIXME: This should *fail* if the value does not fit in the requets integer type
- visitor.visit_u16(self.into_uint()? as u16)
+ let num = try_convert_number!(unsigned, self, "16");
+ visitor.visit_u16(num)
}
#[inline]
fn deserialize_u32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- // FIXME: This should *fail* if the value does not fit in the requets integer type
- visitor.visit_u32(self.into_uint()? as u32)
+ let num = try_convert_number!(unsigned, self, "32");
+ visitor.visit_u32(num)
}
#[inline]
fn deserialize_u64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- // FIXME: This should *fail* if the value does not fit in the requets integer type
- visitor.visit_u64(self.into_uint()? as u64)
+ let num = try_convert_number!(unsigned, self, "u64");
+ visitor.visit_u64(num)
}
#[inline]
@@ -356,49 +382,50 @@ impl<'de> de::Deserializer<'de> for Config {
#[inline]
fn deserialize_i8<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- // FIXME: This should *fail* if the value does not fit in the requets integer type
- visitor.visit_i8(self.cache.into_int()? as i8)
+ let num = try_convert_number!(signed, self.cache, "8");
+ visitor.visit_i8(num)
}
#[inline]
fn deserialize_i16<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- // FIXME: This should *fail* if the value does not fit in the requets integer type
- visitor.visit_i16(self.cache.into_int()? as i16)
+ let num = try_convert_number!(signed, self.cache, "16");
+ visitor.visit_i16(num)
}
#[inline]
fn deserialize_i32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- // FIXME: This should *fail* if the value does not fit in the requets integer type
- visitor.visit_i32(self.cache.into_int()? as i32)
+ let num = try_convert_number!(signed, self.cache, "32");
+ visitor.visit_i32(num)
}
#[inline]
fn deserialize_i64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- visitor.visit_i64(self.cache.into_int()?)
+ let num = try_convert_number!(signed, self.cache, "64");
+ visitor.visit_i64(num)
}
#[inline]
fn deserialize_u8<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- // FIXME: This should *fail* if the value does not fit in the requets integer type
- visitor.visit_u8(self.cache.into_int()? as u8)
+ let num = try_convert_number!(unsigned, self.cache, "8");
+ visitor.visit_u8(num)
}
#[inline]
fn deserialize_u16<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- // FIXME: This should *fail* if the value does not fit in the requets integer type
- visitor.visit_u16(self.cache.into_int()? as u16)
+ let num = try_convert_number!(unsigned, self.cache, "16");
+ visitor.visit_u16(num)
}
#[inline]
fn deserialize_u32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- // FIXME: This should *fail* if the value does not fit in the requets integer type
- visitor.visit_u32(self.cache.into_int()? as u32)
+ let num = try_convert_number!(unsigned, self.cache, "32");
+ visitor.visit_u32(num)
}
#[inline]
fn deserialize_u64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- // FIXME: This should *fail* if the value does not fit in the requets integer type
- visitor.visit_u64(self.cache.into_int()? as u64)
+ let num = try_convert_number!(unsigned, self.cache, "64");
+ visitor.visit_u64(num)
}
#[inline]
diff --git a/src/value.rs b/src/value.rs
index c9536f7..40cbfe6 100644
--- a/src/value.rs
+++ b/src/value.rs
@@ -761,15 +761,30 @@ impl<'de> Deserialize<'de> for Value {
}
#[inline]
- fn visit_u64<E>(self, value: u64) -> ::std::result::Result<Value, E> {
- // FIXME: This is bad
- Ok((value as i64).into())
+ fn visit_u64<E>(self, value: u64) -> ::std::result::Result<Value, E>
+ where
+ E: ::serde::de::Error,
+ {
+ let num: i64 = value.try_into().map_err(|_| {
+ E::invalid_type(::serde::de::Unexpected::Unsigned(value), &self)
+ })?;
+ Ok(num.into())
}
#[inline]
- fn visit_u128<E>(self, value: u128) -> ::std::result::Result<Value, E> {
- // FIXME: This is bad
- Ok((value as i128).into())
+ fn visit_u128<E>(self, value: u128) -> ::std::result::Result<Value, E>
+ where
+ E: ::serde::de::Error,
+ {
+ let num: i128 = value.try_into().map_err(|_| {
+ E::invalid_type(
+ ::serde::de::Unexpected::Other(
+ format!("integer `{value}` as u128").as_str(),
+ ),
+ &self,
+ )
+ })?;
+ Ok(num.into())
}
#[inline]
diff --git a/tests/integer_range.rs b/tests/integer_range.rs
index 7777ef2..e80a2f2 100644
--- a/tests/integer_range.rs
+++ b/tests/integer_range.rs
@@ -13,8 +13,14 @@ fn wrapping_u16() {
.build()
.unwrap();
- let port: u16 = c.get("settings.port").unwrap();
- assert_eq!(port, 464);
+ // FIXME: Can't compare ConfigError, because Unexpected are private.
+ let _port_error = c.get::<u16>("settings.port").unwrap_err();
+ /*
+ assert!(matches!(
+ Err(ConfigError::invalid_type(None, config::Unexpected::U64(66000), "an unsigned 16 bit integer"),)
+ port_error
+ ));
+ */
}
#[test]