Skip to content

Commit

Permalink
Add support for unsigned integers
Browse files Browse the repository at this point in the history
Signed-off-by: Matthias Beyer <[email protected]>
  • Loading branch information
matthiasbeyer committed Mar 19, 2021
1 parent d89111d commit c157bf6
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 1 deletion.
4 changes: 4 additions & 0 deletions src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ impl<'de> de::Deserializer<'de> for Value {
ValueKind::Nil => visitor.visit_unit(),
ValueKind::I64(i) => visitor.visit_i64(i),
ValueKind::I128(i) => visitor.visit_i128(i),
ValueKind::U64(i) => visitor.visit_u64(i),
ValueKind::U128(i) => visitor.visit_u128(i),
ValueKind::Boolean(b) => visitor.visit_bool(b),
ValueKind::Float(f) => visitor.visit_f64(f),
ValueKind::String(s) => visitor.visit_string(s),
Expand Down Expand Up @@ -351,6 +353,8 @@ impl<'de> de::Deserializer<'de> for Config {
ValueKind::Nil => visitor.visit_unit(),
ValueKind::I64(i) => visitor.visit_i64(i),
ValueKind::I128(i) => visitor.visit_i128(i),
ValueKind::U64(i) => visitor.visit_u64(i),
ValueKind::U128(i) => visitor.visit_u128(i),
ValueKind::Boolean(b) => visitor.visit_bool(b),
ValueKind::Float(f) => visitor.visit_f64(f),
ValueKind::String(s) => visitor.visit_string(s),
Expand Down
4 changes: 4 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub enum Unexpected {
Bool(bool),
I64(i64),
I128(i128),
U64(u64),
U128(u128),
Float(f64),
Str(String),
Unit,
Expand All @@ -24,6 +26,8 @@ impl fmt::Display for Unexpected {
Unexpected::Bool(b) => write!(f, "boolean `{}`", b),
Unexpected::I64(i) => write!(f, "integer 64 bit `{}`", i),
Unexpected::I128(i) => write!(f, "integer 128 bit `{}`", i),
Unexpected::U64(i) => write!(f, "unsigned integer 64 bit `{}`", i),
Unexpected::U128(i) => write!(f, "unsigned integer 128 bit `{}`", i),
Unexpected::Float(v) => write!(f, "floating point `{}`", v),
Unexpected::Str(ref s) => write!(f, "string {:?}", s),
Unexpected::Unit => write!(f, "unit value"),
Expand Down
193 changes: 192 additions & 1 deletion src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub enum ValueKind {
Boolean(bool),
I64(i64),
I128(i128),
U64(u64),
U128(u128),
Float(f64),
String(String),
Table(Table),
Expand Down Expand Up @@ -80,6 +82,36 @@ impl From<i128> for ValueKind {
}
}

impl From<u8> for ValueKind {
fn from(value: u8) -> Self {
ValueKind::U64(value as u64)
}
}

impl From<u16> for ValueKind {
fn from(value: u16) -> Self {
ValueKind::U64(value as u64)
}
}

impl From<u32> for ValueKind {
fn from(value: u32) -> Self {
ValueKind::U64(value as u64)
}
}

impl From<u64> for ValueKind {
fn from(value: u64) -> Self {
ValueKind::U64(value)
}
}

impl From<u128> for ValueKind {
fn from(value: u128) -> Self {
ValueKind::U128(value)
}
}

impl From<f64> for ValueKind {
fn from(value: f64) -> Self {
ValueKind::Float(value)
Expand Down Expand Up @@ -129,6 +161,8 @@ impl Display for ValueKind {
ValueKind::Boolean(value) => write!(f, "{}", value),
ValueKind::I64(value) => write!(f, "{}", value),
ValueKind::I128(value) => write!(f, "{}", value),
ValueKind::U64(value) => write!(f, "{}", value),
ValueKind::U128(value) => write!(f, "{}", value),
ValueKind::Float(value) => write!(f, "{}", value),
ValueKind::Nil => write!(f, "nil"),

Expand Down Expand Up @@ -188,6 +222,8 @@ impl Value {
ValueKind::Boolean(value) => Ok(value),
ValueKind::I64(value) => Ok(value != 0),
ValueKind::I128(value) => Ok(value != 0),
ValueKind::U64(value) => Ok(value != 0),
ValueKind::U128(value) => Ok(value != 0),
ValueKind::Float(value) => Ok(value != 0.0),

ValueKind::String(ref value) => {
Expand Down Expand Up @@ -231,7 +267,17 @@ impl Value {
ValueKind::I128(value) => Err(ConfigError::invalid_type(
self.origin,
Unexpected::I128(value),
"an 64 bit or less integer",
"an signed 64 bit or less integer",
)),
ValueKind::U64(value) => Err(ConfigError::invalid_type(
self.origin,
Unexpected::U64(value),
"an signed 64 bit or less integer",
)),
ValueKind::U128(value) => Err(ConfigError::invalid_type(
self.origin,
Unexpected::U128(value),
"an signed 64 bit or less integer",
)),

ValueKind::String(ref s) => {
Expand Down Expand Up @@ -278,6 +324,12 @@ impl Value {
match self.kind {
ValueKind::I64(value) => Ok(value as i128),
ValueKind::I128(value) => Ok(value),
ValueKind::U64(value) => Ok(value as i128),
ValueKind::U128(value) => Err(ConfigError::invalid_type(
self.origin,
Unexpected::U128(value),
"an signed 128 bit integer",
)),

ValueKind::String(ref s) => {
match s.to_lowercase().as_ref() {
Expand Down Expand Up @@ -318,6 +370,121 @@ impl Value {
}
}

/// Returns `self` into an u64, if possible.
// FIXME: Should this not be `try_into_*` ?
pub fn into_uint(self) -> Result<u64> {
match self.kind {
ValueKind::U64(value) => Ok(value),
ValueKind::U128(value) => Err(ConfigError::invalid_type(
self.origin,
Unexpected::U128(value),
"an unsigned 64 bit or less integer",
)),
ValueKind::I64(value) => Err(ConfigError::invalid_type(
self.origin,
Unexpected::I64(value),
"an unsigned 64 bit or less integer",
)),
ValueKind::I128(value) => Err(ConfigError::invalid_type(
self.origin,
Unexpected::I128(value),
"an unsigned 64 bit or less integer",
)),

ValueKind::String(ref s) => {
match s.to_lowercase().as_ref() {
"true" | "on" | "yes" => Ok(1),
"false" | "off" | "no" => Ok(0),
_ => {
s.parse().map_err(|_| {
// Unexpected string
ConfigError::invalid_type(
self.origin.clone(),
Unexpected::Str(s.clone()),
"an integer",
)
})
}
}
}

ValueKind::Boolean(value) => Ok(if value { 1 } else { 0 }),
ValueKind::Float(value) => Ok(value.round() as u64),

// Unexpected type
ValueKind::Nil => Err(ConfigError::invalid_type(
self.origin,
Unexpected::Unit,
"an integer",
)),
ValueKind::Table(_) => Err(ConfigError::invalid_type(
self.origin,
Unexpected::Map,
"an integer",
)),
ValueKind::Array(_) => Err(ConfigError::invalid_type(
self.origin,
Unexpected::Seq,
"an integer",
)),
}
}

/// Returns `self` into an u128, if possible.
pub fn into_uint128(self) -> Result<u128> {
match self.kind {
ValueKind::U64(value) => Ok(value as u128),
ValueKind::U128(value) => Ok(value),
ValueKind::I64(value) => Err(ConfigError::invalid_type(
self.origin,
Unexpected::I64(value),
"an unsigned 128 bit or less integer",
)),
ValueKind::I128(value) => Err(ConfigError::invalid_type(
self.origin,
Unexpected::I128(value),
"an unsigned 128 bit or less integer",
)),

ValueKind::String(ref s) => {
match s.to_lowercase().as_ref() {
"true" | "on" | "yes" => Ok(1),
"false" | "off" | "no" => Ok(0),
_ => {
s.parse().map_err(|_| {
// Unexpected string
ConfigError::invalid_type(
self.origin.clone(),
Unexpected::Str(s.clone()),
"an integer",
)
})
}
}
}

ValueKind::Boolean(value) => Ok(if value { 1 } else { 0 }),
ValueKind::Float(value) => Ok(value.round() as u128),

// Unexpected type
ValueKind::Nil => Err(ConfigError::invalid_type(
self.origin,
Unexpected::Unit,
"an integer",
)),
ValueKind::Table(_) => Err(ConfigError::invalid_type(
self.origin,
Unexpected::Map,
"an integer",
)),
ValueKind::Array(_) => Err(ConfigError::invalid_type(
self.origin,
Unexpected::Seq,
"an integer",
)),
}
}

/// Returns `self` into a f64, if possible.
// FIXME: Should this not be `try_into_*` ?
pub fn into_float(self) -> Result<f64> {
Expand All @@ -343,6 +510,8 @@ impl Value {

ValueKind::I64(value) => Ok(value as f64),
ValueKind::I128(value) => Ok(value as f64),
ValueKind::U64(value) => Ok(value as f64),
ValueKind::U128(value) => Ok(value as f64),
ValueKind::Boolean(value) => Ok(if value { 1.0 } else { 0.0 }),

// Unexpected type
Expand Down Expand Up @@ -373,6 +542,8 @@ impl Value {
ValueKind::Boolean(value) => Ok(value.to_string()),
ValueKind::I64(value) => Ok(value.to_string()),
ValueKind::I128(value) => Ok(value.to_string()),
ValueKind::U64(value) => Ok(value.to_string()),
ValueKind::U128(value) => Ok(value.to_string()),
ValueKind::Float(value) => Ok(value.to_string()),

// Cannot convert
Expand Down Expand Up @@ -421,6 +592,16 @@ impl Value {
Unexpected::I128(value),
"an array",
)),
ValueKind::U64(value) => Err(ConfigError::invalid_type(
self.origin,
Unexpected::U64(value),
"an array",
)),
ValueKind::U128(value) => Err(ConfigError::invalid_type(
self.origin,
Unexpected::U128(value),
"an array",
)),
ValueKind::Boolean(value) => Err(ConfigError::invalid_type(
self.origin,
Unexpected::Bool(value),
Expand Down Expand Up @@ -466,6 +647,16 @@ impl Value {
Unexpected::I128(value),
"a map",
)),
ValueKind::U64(value) => Err(ConfigError::invalid_type(
self.origin,
Unexpected::U64(value),
"a map",
)),
ValueKind::U128(value) => Err(ConfigError::invalid_type(
self.origin,
Unexpected::U128(value),
"a map",
)),
ValueKind::Boolean(value) => Err(ConfigError::invalid_type(
self.origin,
Unexpected::Bool(value),
Expand Down

0 comments on commit c157bf6

Please sign in to comment.