Skip to content

Commit 3248393

Browse files
committed
Add support for unsigned integers
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
1 parent b8f82b2 commit 3248393

3 files changed

Lines changed: 200 additions & 1 deletion

File tree

src/de.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ impl<'de> de::Deserializer<'de> for Value {
2020
ValueKind::Nil => visitor.visit_unit(),
2121
ValueKind::I64(i) => visitor.visit_i64(i),
2222
ValueKind::I128(i) => visitor.visit_i128(i),
23+
ValueKind::U64(i) => visitor.visit_u64(i),
24+
ValueKind::U128(i) => visitor.visit_u128(i),
2325
ValueKind::Boolean(b) => visitor.visit_bool(b),
2426
ValueKind::Float(f) => visitor.visit_f64(f),
2527
ValueKind::String(s) => visitor.visit_string(s),
@@ -347,6 +349,8 @@ impl<'de> de::Deserializer<'de> for Config {
347349
ValueKind::Nil => visitor.visit_unit(),
348350
ValueKind::I64(i) => visitor.visit_i64(i),
349351
ValueKind::I128(i) => visitor.visit_i128(i),
352+
ValueKind::U64(i) => visitor.visit_u64(i),
353+
ValueKind::U128(i) => visitor.visit_u128(i),
350354
ValueKind::Boolean(b) => visitor.visit_bool(b),
351355
ValueKind::Float(f) => visitor.visit_f64(f),
352356
ValueKind::String(s) => visitor.visit_string(s),

src/error.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ pub enum Unexpected {
1010
Bool(bool),
1111
I64(i64),
1212
I128(i128),
13+
U64(u64),
14+
U128(u128),
1315
Float(f64),
1416
Str(String),
1517
Unit,
@@ -23,6 +25,8 @@ impl fmt::Display for Unexpected {
2325
Unexpected::Bool(b) => write!(f, "boolean `{}`", b),
2426
Unexpected::I64(i) => write!(f, "integer 64 bit `{}`", i),
2527
Unexpected::I128(i) => write!(f, "integer 128 bit `{}`", i),
28+
Unexpected::U64(i) => write!(f, "unsigned integer 64 bit `{}`", i),
29+
Unexpected::U128(i) => write!(f, "unsigned integer 128 bit `{}`", i),
2630
Unexpected::Float(v) => write!(f, "floating point `{}`", v),
2731
Unexpected::Str(ref s) => write!(f, "string {:?}", s),
2832
Unexpected::Unit => write!(f, "unit value"),

src/value.rs

Lines changed: 192 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ pub enum ValueKind {
1313
Boolean(bool),
1414
I64(i64),
1515
I128(i128),
16+
U64(u64),
17+
U128(u128),
1618
Float(f64),
1719
String(String),
1820
Table(Table),
@@ -82,6 +84,36 @@ impl From<i128> for ValueKind {
8284
}
8385
}
8486

87+
impl From<u8> for ValueKind {
88+
fn from(value: u8) -> Self {
89+
ValueKind::U64(value as u64)
90+
}
91+
}
92+
93+
impl From<u16> for ValueKind {
94+
fn from(value: u16) -> Self {
95+
ValueKind::U64(value as u64)
96+
}
97+
}
98+
99+
impl From<u32> for ValueKind {
100+
fn from(value: u32) -> Self {
101+
ValueKind::U64(value as u64)
102+
}
103+
}
104+
105+
impl From<u64> for ValueKind {
106+
fn from(value: u64) -> Self {
107+
ValueKind::U64(value)
108+
}
109+
}
110+
111+
impl From<u128> for ValueKind {
112+
fn from(value: u128) -> Self {
113+
ValueKind::U128(value)
114+
}
115+
}
116+
85117
impl From<f64> for ValueKind {
86118
fn from(value: f64) -> Self {
87119
ValueKind::Float(value)
@@ -120,6 +152,8 @@ impl Display for ValueKind {
120152
ValueKind::Boolean(value) => write!(f, "{}", value),
121153
ValueKind::I64(value) => write!(f, "{}", value),
122154
ValueKind::I128(value) => write!(f, "{}", value),
155+
ValueKind::U64(value) => write!(f, "{}", value),
156+
ValueKind::U128(value) => write!(f, "{}", value),
123157
ValueKind::Float(value) => write!(f, "{}", value),
124158
ValueKind::Nil => write!(f, "nil"),
125159
ValueKind::Table(ref table) => write!(f, "{{ {} }}", {
@@ -184,6 +218,8 @@ impl Value {
184218
ValueKind::Boolean(value) => Ok(value),
185219
ValueKind::I64(value) => Ok(value != 0),
186220
ValueKind::I128(value) => Ok(value != 0),
221+
ValueKind::U64(value) => Ok(value != 0),
222+
ValueKind::U128(value) => Ok(value != 0),
187223
ValueKind::Float(value) => Ok(value != 0.0),
188224

189225
ValueKind::String(ref value) => {
@@ -227,7 +263,17 @@ impl Value {
227263
ValueKind::I128(value) => Err(ConfigError::invalid_type(
228264
self.origin,
229265
Unexpected::I128(value),
230-
"an 64 bit or less integer",
266+
"an signed 64 bit or less integer",
267+
)),
268+
ValueKind::U64(value) => Err(ConfigError::invalid_type(
269+
self.origin,
270+
Unexpected::U64(value),
271+
"an signed 64 bit or less integer",
272+
)),
273+
ValueKind::U128(value) => Err(ConfigError::invalid_type(
274+
self.origin,
275+
Unexpected::U128(value),
276+
"an signed 64 bit or less integer",
231277
)),
232278

233279
ValueKind::String(ref s) => {
@@ -274,6 +320,12 @@ impl Value {
274320
match self.kind {
275321
ValueKind::I64(value) => Ok(value as i128),
276322
ValueKind::I128(value) => Ok(value),
323+
ValueKind::U64(value) => Ok(value as i128),
324+
ValueKind::U128(value) => Err(ConfigError::invalid_type(
325+
self.origin,
326+
Unexpected::U128(value),
327+
"an signed 128 bit integer",
328+
)),
277329

278330
ValueKind::String(ref s) => {
279331
match s.to_lowercase().as_ref() {
@@ -314,6 +366,121 @@ impl Value {
314366
}
315367
}
316368

369+
/// Returns `self` into an u64, if possible.
370+
// FIXME: Should this not be `try_into_*` ?
371+
pub fn into_uint(self) -> Result<u64> {
372+
match self.kind {
373+
ValueKind::U64(value) => Ok(value),
374+
ValueKind::U128(value) => Err(ConfigError::invalid_type(
375+
self.origin,
376+
Unexpected::U128(value),
377+
"an unsigned 64 bit or less integer",
378+
)),
379+
ValueKind::I64(value) => Err(ConfigError::invalid_type(
380+
self.origin,
381+
Unexpected::I64(value),
382+
"an unsigned 64 bit or less integer",
383+
)),
384+
ValueKind::I128(value) => Err(ConfigError::invalid_type(
385+
self.origin,
386+
Unexpected::I128(value),
387+
"an unsigned 64 bit or less integer",
388+
)),
389+
390+
ValueKind::String(ref s) => {
391+
match s.to_lowercase().as_ref() {
392+
"true" | "on" | "yes" => Ok(1),
393+
"false" | "off" | "no" => Ok(0),
394+
_ => {
395+
s.parse().map_err(|_| {
396+
// Unexpected string
397+
ConfigError::invalid_type(
398+
self.origin.clone(),
399+
Unexpected::Str(s.clone()),
400+
"an integer",
401+
)
402+
})
403+
}
404+
}
405+
}
406+
407+
ValueKind::Boolean(value) => Ok(if value { 1 } else { 0 }),
408+
ValueKind::Float(value) => Ok(value.round() as u64),
409+
410+
// Unexpected type
411+
ValueKind::Nil => Err(ConfigError::invalid_type(
412+
self.origin,
413+
Unexpected::Unit,
414+
"an integer",
415+
)),
416+
ValueKind::Table(_) => Err(ConfigError::invalid_type(
417+
self.origin,
418+
Unexpected::Map,
419+
"an integer",
420+
)),
421+
ValueKind::Array(_) => Err(ConfigError::invalid_type(
422+
self.origin,
423+
Unexpected::Seq,
424+
"an integer",
425+
)),
426+
}
427+
}
428+
429+
/// Returns `self` into an u128, if possible.
430+
pub fn into_uint128(self) -> Result<u128> {
431+
match self.kind {
432+
ValueKind::U64(value) => Ok(value as u128),
433+
ValueKind::U128(value) => Ok(value),
434+
ValueKind::I64(value) => Err(ConfigError::invalid_type(
435+
self.origin,
436+
Unexpected::I64(value),
437+
"an unsigned 128 bit or less integer",
438+
)),
439+
ValueKind::I128(value) => Err(ConfigError::invalid_type(
440+
self.origin,
441+
Unexpected::I128(value),
442+
"an unsigned 128 bit or less integer",
443+
)),
444+
445+
ValueKind::String(ref s) => {
446+
match s.to_lowercase().as_ref() {
447+
"true" | "on" | "yes" => Ok(1),
448+
"false" | "off" | "no" => Ok(0),
449+
_ => {
450+
s.parse().map_err(|_| {
451+
// Unexpected string
452+
ConfigError::invalid_type(
453+
self.origin.clone(),
454+
Unexpected::Str(s.clone()),
455+
"an integer",
456+
)
457+
})
458+
}
459+
}
460+
}
461+
462+
ValueKind::Boolean(value) => Ok(if value { 1 } else { 0 }),
463+
ValueKind::Float(value) => Ok(value.round() as u128),
464+
465+
// Unexpected type
466+
ValueKind::Nil => Err(ConfigError::invalid_type(
467+
self.origin,
468+
Unexpected::Unit,
469+
"an integer",
470+
)),
471+
ValueKind::Table(_) => Err(ConfigError::invalid_type(
472+
self.origin,
473+
Unexpected::Map,
474+
"an integer",
475+
)),
476+
ValueKind::Array(_) => Err(ConfigError::invalid_type(
477+
self.origin,
478+
Unexpected::Seq,
479+
"an integer",
480+
)),
481+
}
482+
}
483+
317484
/// Returns `self` into a f64, if possible.
318485
// FIXME: Should this not be `try_into_*` ?
319486
pub fn into_float(self) -> Result<f64> {
@@ -339,6 +506,8 @@ impl Value {
339506

340507
ValueKind::I64(value) => Ok(value as f64),
341508
ValueKind::I128(value) => Ok(value as f64),
509+
ValueKind::U64(value) => Ok(value as f64),
510+
ValueKind::U128(value) => Ok(value as f64),
342511
ValueKind::Boolean(value) => Ok(if value { 1.0 } else { 0.0 }),
343512

344513
// Unexpected type
@@ -369,6 +538,8 @@ impl Value {
369538
ValueKind::Boolean(value) => Ok(value.to_string()),
370539
ValueKind::I64(value) => Ok(value.to_string()),
371540
ValueKind::I128(value) => Ok(value.to_string()),
541+
ValueKind::U64(value) => Ok(value.to_string()),
542+
ValueKind::U128(value) => Ok(value.to_string()),
372543
ValueKind::Float(value) => Ok(value.to_string()),
373544

374545
// Cannot convert
@@ -417,6 +588,16 @@ impl Value {
417588
Unexpected::I128(value),
418589
"an array",
419590
)),
591+
ValueKind::U64(value) => Err(ConfigError::invalid_type(
592+
self.origin,
593+
Unexpected::U64(value),
594+
"an array",
595+
)),
596+
ValueKind::U128(value) => Err(ConfigError::invalid_type(
597+
self.origin,
598+
Unexpected::U128(value),
599+
"an array",
600+
)),
420601
ValueKind::Boolean(value) => Err(ConfigError::invalid_type(
421602
self.origin,
422603
Unexpected::Bool(value),
@@ -462,6 +643,16 @@ impl Value {
462643
Unexpected::I128(value),
463644
"a map",
464645
)),
646+
ValueKind::U64(value) => Err(ConfigError::invalid_type(
647+
self.origin,
648+
Unexpected::U64(value),
649+
"a map",
650+
)),
651+
ValueKind::U128(value) => Err(ConfigError::invalid_type(
652+
self.origin,
653+
Unexpected::U128(value),
654+
"a map",
655+
)),
465656
ValueKind::Boolean(value) => Err(ConfigError::invalid_type(
466657
self.origin,
467658
Unexpected::Bool(value),

0 commit comments

Comments
 (0)