From 7da5d5b40c5fde430271be8360f01588031db25f Mon Sep 17 00:00:00 2001 From: Septen Date: Sun, 13 Jun 2021 01:06:04 +0300 Subject: [PATCH 01/16] JSON: add unit tests. --- src/json.rs | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 +- 2 files changed, 164 insertions(+), 1 deletion(-) diff --git a/src/json.rs b/src/json.rs index 518257692..650b436e3 100644 --- a/src/json.rs +++ b/src/json.rs @@ -1,6 +1,9 @@ use super::prelude::*; +#[cfg(feature = "engine")] use alloc::collections::BTreeMap; +#[cfg(test)] +use std::collections::BTreeMap; use core::convert::From; use rjson::{Array, Null, Object, Value}; @@ -13,6 +16,7 @@ pub enum JsonValue { Object(BTreeMap), } +#[cfg_attr(test, derive(PartialEq))] pub enum JsonError { NotJsonType, MissingValue, @@ -115,6 +119,20 @@ impl AsRef<[u8]> for JsonError { } } +#[cfg(test)] +impl std::fmt::Debug for JsonError { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + f.write_fmt(format_args!("{}", std::str::from_utf8(self.as_ref()).unwrap())) + } +} + +#[cfg(test)] +impl std::fmt::Display for JsonError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_fmt(format_args!("{:?}", *self)) + } +} + impl Array for JsonArray { fn new() -> Self { JsonArray(Vec::new()) @@ -196,3 +214,148 @@ pub fn parse_json(data: &[u8]) -> Option { let mut index = 0; rjson::parse::(&*data_array, &mut index) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_json_type_string() { + let json = parse_json(format!(r#"{{"foo": "{}"}}"#, "abcd").as_bytes()).unwrap(); + let string = json.string("foo").ok().unwrap(); + assert_eq!(string, "abcd"); + + let json = parse_json(format!(r#"{{"foo": {}}}"#, 123).as_bytes()).unwrap(); + let err = json.string("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidString); + + let json = parse_json(format!(r#"{{"foo": {}}}"#, true).as_bytes()).unwrap(); + let err = json.string("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidString); + + let json = parse_json(format!(r#"{{"foo": ["{}"]}}"#, "abcd").as_bytes()).unwrap(); + let err = json.string("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidString); + + let json = JsonValue::Null; + let err = json.string("foo").unwrap_err(); + assert_eq!(err, JsonError::NotJsonType); + } + + #[test] + fn test_json_type_u64() { + let json = parse_json(format!(r#"{{"foo": {}}}"#, 123).as_bytes()).unwrap(); + let val = json.u64("foo").ok().unwrap(); + assert_eq!(val, 123); + + let json = parse_json(format!(r#"{{"foo": "{}"}}"#, "bar").as_bytes()).unwrap(); + let err = json.u64("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidU64); + + let json = parse_json(format!(r#"{{"foo": "{}"}}"#, "123").as_bytes()).unwrap(); + let err = json.u64("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidU64); + + let json = parse_json(format!(r#"{{"foo": {}}}"#, true).as_bytes()).unwrap(); + let err = json.u64("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidU64); + + let json = parse_json(format!(r#"{{"foo": [{}]}}"#, 123).as_bytes()).unwrap(); + let err = json.u64("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidU64); + + let json = JsonValue::Null; + let err = json.u64("foo").unwrap_err(); + assert_eq!(err, JsonError::NotJsonType); + } + + #[test] + fn test_json_type_u128() { + let json = parse_json(format!(r#"{{"foo": "{}"}}"#, 123).as_bytes()).unwrap(); + let val = json.u128("foo").ok().unwrap(); + assert_eq!(val, 123); + + let json = parse_json(format!(r#"{{"foo": {}}}"#, 123).as_bytes()).unwrap(); + let err = json.u128("foo").unwrap_err(); + assert_eq!(err, JsonError::ExpectedStringGotNumber); + + let json = parse_json(format!(r#"{{"foo": "{}"}}"#, "bar").as_bytes()).unwrap(); + let err = json.u128("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidU128); + + let json = parse_json(format!(r#"{{"foo": {}}}"#, true).as_bytes()).unwrap(); + let err = json.u128("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidU128); + + let json = parse_json(format!(r#"{{"foo": ["{}"]}}"#, 123).as_bytes()).unwrap(); + let err = json.u128("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidU128); + + let json = JsonValue::Null; + let err = json.u128("foo").unwrap_err(); + assert_eq!(err, JsonError::NotJsonType); + } + + #[test] + fn test_json_type_bool() { + let json = parse_json(format!(r#"{{"foo": {}}}"#, true).as_bytes()).unwrap(); + let val = json.bool("foo").ok().unwrap(); + assert_eq!(val, true); + + let json = parse_json(format!(r#"{{"foo": {}}}"#, false).as_bytes()).unwrap(); + let val = json.bool("foo").ok().unwrap(); + assert_eq!(val, false); + + let json = parse_json(format!(r#"{{"foo": "{}"}}"#, true).as_bytes()).unwrap(); + let err = json.bool("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidBool); + + let json = parse_json(format!(r#"{{"foo": "{}"}}"#, false).as_bytes()).unwrap(); + let err = json.bool("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidBool); + + let json = parse_json(format!(r#"{{"foo": [{}]}}"#, true).as_bytes()).unwrap(); + let err = json.bool("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidBool); + + let json = parse_json(format!(r#"{{"foo": {}}}"#, 123).as_bytes()).unwrap(); + let err = json.bool("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidBool); + + let json = parse_json(format!(r#"{{"foo": "{}"}}"#, "bar").as_bytes()).unwrap(); + let err = json.bool("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidBool); + + let json = JsonValue::Null; + let err = json.bool("foo").unwrap_err(); + assert_eq!(err, JsonError::NotJsonType); + } + + #[test] + fn test_json_type_u8() { + let json = JsonValue::from(123f64); + let val = JsonValue::parse_u8(&json).ok().unwrap(); + assert_eq!(val, 123); + + let json = JsonValue::from(256f64); + let val = JsonValue::parse_u8(&json).ok().unwrap(); + assert_eq!(val, 255); + + let json = JsonValue::from(260f64); + let val = JsonValue::parse_u8(&json).ok().unwrap(); + assert_eq!(val, 255); + + let json = JsonValue::from(12345678f64); + let val = JsonValue::parse_u8(&json).ok().unwrap(); + assert_eq!(val, 255); + + let json = JsonValue::from("abcd".to_string()); + let err = JsonValue::parse_u8(&json).unwrap_err(); + assert_eq!(err, JsonError::InvalidU8); + } + + #[test] + fn test_json_type_array() { + //TODO + } +} diff --git a/src/lib.rs b/src/lib.rs index 387df1670..037940f71 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,7 +27,7 @@ mod deposit_event; pub mod engine; #[cfg(any(feature = "engine", test))] mod fungible_token; -#[cfg(feature = "engine")] +#[cfg(any(feature = "engine", test))] mod json; #[cfg(feature = "engine")] mod log_entry; From 973c225627c6def4b616afbd68aa7088719f0060 Mon Sep 17 00:00:00 2001 From: Septen Date: Sun, 13 Jun 2021 01:33:32 +0300 Subject: [PATCH 02/16] JSON: fix `u8`, `u64` out-of-range behaviour. --- src/json.rs | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/src/json.rs b/src/json.rs index 650b436e3..65171f5e1 100644 --- a/src/json.rs +++ b/src/json.rs @@ -27,6 +27,8 @@ pub enum JsonError { InvalidString, InvalidArray, ExpectedStringGotNumber, + OutOfRangeU8, + OutOfRangeU64, } pub struct JsonArray(Vec); @@ -48,7 +50,14 @@ impl JsonValue { pub fn u64(&self, key: &str) -> Result { match self { JsonValue::Object(o) => match o.get(key).ok_or(JsonError::MissingValue)? { - JsonValue::Number(n) => Ok(*n as u64), + JsonValue::Number(n) => { + // Upper bound is covered by the type limitation + if *n < u64::MIN as f64 { + Err(JsonError::OutOfRangeU64) + } else { + Ok(*n as u64) + } + } _ => Err(JsonError::InvalidU64), }, _ => Err(JsonError::NotJsonType), @@ -83,7 +92,13 @@ impl JsonValue { #[allow(dead_code)] pub fn parse_u8(v: &JsonValue) -> Result { match v { - JsonValue::Number(n) => Ok(*n as u8), + JsonValue::Number(n) => { + if *n < u8::MIN as f64 || *n > u8::MAX as f64 { + Err(JsonError::OutOfRangeU8) + } else { + Ok(*n as u8) + } + } _ => Err(JsonError::InvalidU8), } } @@ -115,6 +130,8 @@ impl AsRef<[u8]> for JsonError { Self::InvalidString => b"ERR_FAILED_PARSE_STRING", Self::InvalidArray => b"ERR_FAILED_PARSE_ARRAY", Self::ExpectedStringGotNumber => b"ERR_EXPECTED_STRING_GOT_NUMBER", + Self::OutOfRangeU8 => b"ERR_OUT_OF_RANGE_U8", + Self::OutOfRangeU64 => b"ERR_OUT_OF_RANGE_U64", } } } @@ -248,6 +265,10 @@ mod tests { let val = json.u64("foo").ok().unwrap(); assert_eq!(val, 123); + let json = parse_json(format!(r#"{{"foo": {}}}"#, -1).as_bytes()).unwrap(); + let err = json.u64("foo").unwrap_err(); + assert_eq!(err, JsonError::OutOfRangeU64); + let json = parse_json(format!(r#"{{"foo": "{}"}}"#, "bar").as_bytes()).unwrap(); let err = json.u64("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidU64); @@ -337,17 +358,13 @@ mod tests { let val = JsonValue::parse_u8(&json).ok().unwrap(); assert_eq!(val, 123); - let json = JsonValue::from(256f64); - let val = JsonValue::parse_u8(&json).ok().unwrap(); - assert_eq!(val, 255); - - let json = JsonValue::from(260f64); - let val = JsonValue::parse_u8(&json).ok().unwrap(); - assert_eq!(val, 255); + let json = JsonValue::from(-1f64); + let err = JsonValue::parse_u8(&json).unwrap_err(); + assert_eq!(err, JsonError::OutOfRangeU8); - let json = JsonValue::from(12345678f64); - let val = JsonValue::parse_u8(&json).ok().unwrap(); - assert_eq!(val, 255); + let json = JsonValue::from(256f64); + let err = JsonValue::parse_u8(&json).unwrap_err(); + assert_eq!(err, JsonError::OutOfRangeU8); let json = JsonValue::from("abcd".to_string()); let err = JsonValue::parse_u8(&json).unwrap_err(); From 64c6ed700ad18a3a4aa8c898e0630520c31537fe Mon Sep 17 00:00:00 2001 From: Septen Date: Sun, 13 Jun 2021 01:40:49 +0300 Subject: [PATCH 03/16] Stylystic fixes. --- src/json.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/json.rs b/src/json.rs index 65171f5e1..f7efbb9b6 100644 --- a/src/json.rs +++ b/src/json.rs @@ -2,10 +2,10 @@ use super::prelude::*; #[cfg(feature = "engine")] use alloc::collections::BTreeMap; -#[cfg(test)] -use std::collections::BTreeMap; use core::convert::From; use rjson::{Array, Null, Object, Value}; +#[cfg(test)] +use std::collections::BTreeMap; pub enum JsonValue { Null, @@ -139,7 +139,10 @@ impl AsRef<[u8]> for JsonError { #[cfg(test)] impl std::fmt::Debug for JsonError { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - f.write_fmt(format_args!("{}", std::str::from_utf8(self.as_ref()).unwrap())) + f.write_fmt(format_args!( + "{}", + std::str::from_utf8(self.as_ref()).unwrap() + )) } } From fe6dbcf905c7399faa3e8e48014c13fa54711408 Mon Sep 17 00:00:00 2001 From: Evgeny Ukhanov Date: Thu, 8 Jul 2021 01:40:14 +0300 Subject: [PATCH 04/16] Extend json tests and fix u128 errors --- src/json.rs | 76 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 19 deletions(-) diff --git a/src/json.rs b/src/json.rs index bc0473137..c3e4d4c47 100644 --- a/src/json.rs +++ b/src/json.rs @@ -17,7 +17,6 @@ pub enum JsonValue { } #[cfg_attr(test, derive(PartialEq))] -#[derive(Debug)] pub enum JsonError { NotJsonType, MissingValue, @@ -30,6 +29,7 @@ pub enum JsonError { ExpectedStringGotNumber, OutOfRangeU8, OutOfRangeU64, + OutOfRangeU128, } #[derive(Debug)] @@ -132,6 +132,7 @@ impl AsRef<[u8]> for JsonError { Self::ExpectedStringGotNumber => b"ERR_EXPECTED_STRING_GOT_NUMBER", Self::OutOfRangeU8 => b"ERR_OUT_OF_RANGE_U8", Self::OutOfRangeU64 => b"ERR_OUT_OF_RANGE_U64", + Self::OutOfRangeU128 => b"ERR_OUT_OF_RANGE_U128", } } } @@ -214,7 +215,15 @@ impl TryFrom<&JsonValue> for u128 { fn try_from(value: &JsonValue) -> Result { match value { - JsonValue::String(n) => Ok(n.parse::().map_err(|_| JsonError::InvalidU128)?), + JsonValue::String(n) => { + if let Ok(x) = n.parse::() { + Ok(x) + } else if n.parse::().is_ok() { + Err(JsonError::OutOfRangeU128) + } else { + Err(JsonError::InvalidU128) + } + } JsonValue::Number(_) => Err(JsonError::ExpectedStringGotNumber), _ => Err(JsonError::InvalidU128), } @@ -253,19 +262,27 @@ mod tests { #[test] fn test_json_type_string() { - let json = parse_json(format!(r#"{{"foo": "{}"}}"#, "abcd").as_bytes()).unwrap(); - let string = json.string("foo").ok().unwrap(); - assert_eq!(string, "abcd"); + let json = parse_json(r#"{"foo": "abcd"}"#.as_bytes()).unwrap(); + let string_data = json.string("foo").ok().unwrap(); + assert_eq!(string_data, "abcd"); - let json = parse_json(format!(r#"{{"foo": {}}}"#, 123).as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": 123}"#.as_bytes()).unwrap(); let err = json.string("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidString); - let json = parse_json(format!(r#"{{"foo": {}}}"#, true).as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": true}"#.as_bytes()).unwrap(); + let err = json.string("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidString); + + let json = parse_json(r#"{"foo": ["abcd"]}"#.as_bytes()).unwrap(); + let err = json.string("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidString); + + let json = parse_json(r#"{"foo": {}}"#.as_bytes()).unwrap(); let err = json.string("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidString); - let json = parse_json(format!(r#"{{"foo": ["{}"]}}"#, "abcd").as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": null}"#.as_bytes()).unwrap(); let err = json.string("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidString); @@ -276,27 +293,35 @@ mod tests { #[test] fn test_json_type_u64() { - let json = parse_json(format!(r#"{{"foo": {}}}"#, 123).as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": 123}"#.as_bytes()).unwrap(); let val = json.u64("foo").ok().unwrap(); assert_eq!(val, 123); - let json = parse_json(format!(r#"{{"foo": {}}}"#, -1).as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": -123}"#.as_bytes()).unwrap(); let err = json.u64("foo").unwrap_err(); assert_eq!(err, JsonError::OutOfRangeU64); - let json = parse_json(format!(r#"{{"foo": "{}"}}"#, "bar").as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": "abcd"}"#.as_bytes()).unwrap(); let err = json.u64("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidU64); - let json = parse_json(format!(r#"{{"foo": "{}"}}"#, "123").as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": "123"}"#.as_bytes()).unwrap(); let err = json.u64("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidU64); - let json = parse_json(format!(r#"{{"foo": {}}}"#, true).as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": true}"#.as_bytes()).unwrap(); + let err = json.u64("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidU64); + + let json = parse_json(r#"{"foo": [123]}"#.as_bytes()).unwrap(); + let err = json.u64("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidU64); + + let json = parse_json(r#"{"foo": {}}"#.as_bytes()).unwrap(); let err = json.u64("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidU64); - let json = parse_json(format!(r#"{{"foo": [{}]}}"#, 123).as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": null}"#.as_bytes()).unwrap(); let err = json.u64("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidU64); @@ -307,23 +332,36 @@ mod tests { #[test] fn test_json_type_u128() { - let json = parse_json(format!(r#"{{"foo": "{}"}}"#, 123).as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": "123"}"#.as_bytes()).unwrap(); let val = json.u128("foo").ok().unwrap(); assert_eq!(val, 123); - let json = parse_json(format!(r#"{{"foo": {}}}"#, 123).as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": "-123"}"#.as_bytes()).unwrap(); + ////let val = json.u128("foo").ok().unwrap(); + let err = json.u128("foo").unwrap_err(); + assert_eq!(err, JsonError::OutOfRangeU128); + + let json = parse_json(r#"{"foo": 123}"#.as_bytes()).unwrap(); let err = json.u128("foo").unwrap_err(); assert_eq!(err, JsonError::ExpectedStringGotNumber); - let json = parse_json(format!(r#"{{"foo": "{}"}}"#, "bar").as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": "abcd"}"#.as_bytes()).unwrap(); let err = json.u128("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidU128); - let json = parse_json(format!(r#"{{"foo": {}}}"#, true).as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": true}"#.as_bytes()).unwrap(); + let err = json.u128("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidU128); + + let json = parse_json(r#"{"foo": ["123"]}"#.as_bytes()).unwrap(); + let err = json.u128("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidU128); + + let json = parse_json(r#"{"foo": {}}"#.as_bytes()).unwrap(); let err = json.u128("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidU128); - let json = parse_json(format!(r#"{{"foo": ["{}"]}}"#, 123).as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": null}"#.as_bytes()).unwrap(); let err = json.u128("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidU128); From d344072a8bb53292bb4e3558613c696a650d2714 Mon Sep 17 00:00:00 2001 From: Evgeny Ukhanov Date: Thu, 8 Jul 2021 02:14:19 +0300 Subject: [PATCH 05/16] Fix ft_on_transfer errors result --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index b50b81bba..ffdd07e92 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -87,7 +87,7 @@ mod contract { }; use crate::json::parse_json; - use crate::prelude::{format, Address, ToString, TryInto, H160, H256, U256}; + use crate::prelude::{Address, ToString, TryInto, H160, H256, U256}; use crate::sdk; use crate::storage::{bytes_to_key, KeyPrefix}; use crate::types::{ @@ -323,7 +323,7 @@ mod contract { let args: NEP141FtOnTransferArgs = parse_json(sdk::read_input().as_slice()) .sdk_unwrap() .try_into() - .map_err(|err| format!("ERR_JSON_{:?}", err)) + .map_err(|err| err) .sdk_unwrap(); if sdk::predecessor_account_id() == sdk::current_account_id() { From c4c41ab1f78e18406fb6c7b1a137226d62a0d492 Mon Sep 17 00:00:00 2001 From: Evgeny Ukhanov Date: Thu, 8 Jul 2021 22:01:45 +0300 Subject: [PATCH 06/16] Extend json-bool tests --- src/json.rs | 67 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 11 deletions(-) diff --git a/src/json.rs b/src/json.rs index c3e4d4c47..93e848fa2 100644 --- a/src/json.rs +++ b/src/json.rs @@ -104,13 +104,19 @@ impl JsonValue { } #[allow(dead_code)] - pub fn array(&self, key: &str, call: F) -> Result, JsonError> + pub fn array(&self, key: &str, mut call: F) -> Result, JsonError> where - F: FnMut(&JsonValue) -> T, + F: FnMut(&JsonValue) -> Result, { match self { JsonValue::Object(o) => match o.get(key).ok_or(JsonError::MissingValue)? { - JsonValue::Array(arr) => Ok(arr.iter().map(call).collect()), + JsonValue::Array(arr) => { + let mut res = vec![]; + for v in arr.iter() { + res.push(call(v)?); + } + Ok(res) + } _ => Err(JsonError::InvalidArray), }, _ => Err(JsonError::NotJsonType), @@ -372,31 +378,39 @@ mod tests { #[test] fn test_json_type_bool() { - let json = parse_json(format!(r#"{{"foo": {}}}"#, true).as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": true}"#.as_bytes()).unwrap(); let val = json.bool("foo").ok().unwrap(); assert_eq!(val, true); - let json = parse_json(format!(r#"{{"foo": {}}}"#, false).as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": false}"#.as_bytes()).unwrap(); let val = json.bool("foo").ok().unwrap(); assert_eq!(val, false); - let json = parse_json(format!(r#"{{"foo": "{}"}}"#, true).as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": "true"}"#.as_bytes()).unwrap(); + let err = json.bool("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidBool); + + let json = parse_json(r#"{"foo": "false"}"#.as_bytes()).unwrap(); + let err = json.bool("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidBool); + + let json = parse_json(r#"{"foo": [true]}"#.as_bytes()).unwrap(); let err = json.bool("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidBool); - let json = parse_json(format!(r#"{{"foo": "{}"}}"#, false).as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": 123}"#.as_bytes()).unwrap(); let err = json.bool("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidBool); - let json = parse_json(format!(r#"{{"foo": [{}]}}"#, true).as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": "abcd"}"#.as_bytes()).unwrap(); let err = json.bool("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidBool); - let json = parse_json(format!(r#"{{"foo": {}}}"#, 123).as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": {}}"#.as_bytes()).unwrap(); let err = json.bool("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidBool); - let json = parse_json(format!(r#"{{"foo": "{}"}}"#, "bar").as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": null}"#.as_bytes()).unwrap(); let err = json.bool("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidBool); @@ -426,6 +440,37 @@ mod tests { #[test] fn test_json_type_array() { - //TODO + let json = parse_json(r#"{"foo": [1, 3, 2]}"#.as_bytes()).unwrap(); + let val = json.array("foo", JsonValue::parse_u8).ok().unwrap(); + assert_eq!(val, vec![1, 3, 2]); + + let json = parse_json(r#"{"foo": []}"#.as_bytes()).unwrap(); + let val = json.array("foo", JsonValue::parse_u8).ok().unwrap(); + let res_data: Vec = vec![]; + assert_eq!(val, res_data); + + let json = parse_json(r#"{"foo": ["abcd"]}"#.as_bytes()).unwrap(); + let err = json.array("foo", JsonValue::parse_u8).unwrap_err(); + assert_eq!(err, JsonError::InvalidU8); + + let json = parse_json(r#"{"foo": "abcd"}"#.as_bytes()).unwrap(); + let err = json.array("foo", JsonValue::parse_u8).unwrap_err(); + assert_eq!(err, JsonError::InvalidArray); + + let json = parse_json(r#"{"foo": true}"#.as_bytes()).unwrap(); + let err = json.array("foo", JsonValue::parse_u8).unwrap_err(); + assert_eq!(err, JsonError::InvalidArray); + + let json = parse_json(r#"{"foo": {}}"#.as_bytes()).unwrap(); + let err = json.array("foo", JsonValue::parse_u8).unwrap_err(); + assert_eq!(err, JsonError::InvalidArray); + + let json = parse_json(r#"{"foo": null}"#.as_bytes()).unwrap(); + let err = json.array("foo", JsonValue::parse_u8).unwrap_err(); + assert_eq!(err, JsonError::InvalidArray); + + let json = JsonValue::Null; + let err = json.array("foo", JsonValue::parse_u8).unwrap_err(); + assert_eq!(err, JsonError::NotJsonType); } } From 889619ca844c56a635b81275dcd42c83721aea80 Mon Sep 17 00:00:00 2001 From: Evgeny Ukhanov Date: Fri, 9 Jul 2021 01:16:27 +0300 Subject: [PATCH 07/16] Modified: json array parser. Added: test_json_type_array --- src/json.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/json.rs b/src/json.rs index 93e848fa2..211e369a7 100644 --- a/src/json.rs +++ b/src/json.rs @@ -440,9 +440,9 @@ mod tests { #[test] fn test_json_type_array() { - let json = parse_json(r#"{"foo": [1, 3, 2]}"#.as_bytes()).unwrap(); + let json = parse_json(r#"{"foo": [1, 3, 2, 100]}"#.as_bytes()).unwrap(); let val = json.array("foo", JsonValue::parse_u8).ok().unwrap(); - assert_eq!(val, vec![1, 3, 2]); + assert_eq!(val, vec![1, 3, 2, 100]); let json = parse_json(r#"{"foo": []}"#.as_bytes()).unwrap(); let val = json.array("foo", JsonValue::parse_u8).ok().unwrap(); From a09dff3a21c4e990e16c57fdbd29d1c221378312 Mon Sep 17 00:00:00 2001 From: Evgeny Ukhanov Date: Fri, 9 Jul 2021 16:56:03 +0300 Subject: [PATCH 08/16] Json: remov map_err, Added derives, Added JsonOutOfRangeError --- src/json.rs | 43 ++++++++++++++++++++++++++++++++++--------- src/lib.rs | 1 - 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/json.rs b/src/json.rs index 211e369a7..c1ca791d0 100644 --- a/src/json.rs +++ b/src/json.rs @@ -16,7 +16,7 @@ pub enum JsonValue { Object(BTreeMap), } -#[cfg_attr(test, derive(PartialEq))] +#[derive(Ord, PartialOrd, Eq, PartialEq)] pub enum JsonError { NotJsonType, MissingValue, @@ -27,12 +27,17 @@ pub enum JsonError { InvalidString, InvalidArray, ExpectedStringGotNumber, + OutOfRange(JsonOutOfRangeError), +} + +#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)] +pub enum JsonOutOfRangeError { OutOfRangeU8, OutOfRangeU64, OutOfRangeU128, } -#[derive(Debug)] +#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)] pub enum ParseError { InvalidAccountId, } @@ -59,7 +64,7 @@ impl JsonValue { JsonValue::Number(n) => { // Upper bound is covered by the type limitation if *n < u64::MIN as f64 { - Err(JsonError::OutOfRangeU64) + Err(JsonError::OutOfRange(JsonOutOfRangeError::OutOfRangeU64)) } else { Ok(*n as u64) } @@ -94,7 +99,7 @@ impl JsonValue { match v { JsonValue::Number(n) => { if *n < u8::MIN as f64 || *n > u8::MAX as f64 { - Err(JsonError::OutOfRangeU8) + Err(JsonError::OutOfRange(JsonOutOfRangeError::OutOfRangeU64)) } else { Ok(*n as u8) } @@ -136,6 +141,14 @@ impl AsRef<[u8]> for JsonError { Self::InvalidString => b"ERR_FAILED_PARSE_STRING", Self::InvalidArray => b"ERR_FAILED_PARSE_ARRAY", Self::ExpectedStringGotNumber => b"ERR_EXPECTED_STRING_GOT_NUMBER", + Self::OutOfRange(err) => err.as_ref(), + } + } +} + +impl AsRef<[u8]> for JsonOutOfRangeError { + fn as_ref(&self) -> &[u8] { + match self { Self::OutOfRangeU8 => b"ERR_OUT_OF_RANGE_U8", Self::OutOfRangeU64 => b"ERR_OUT_OF_RANGE_U64", Self::OutOfRangeU128 => b"ERR_OUT_OF_RANGE_U128", @@ -225,7 +238,7 @@ impl TryFrom<&JsonValue> for u128 { if let Ok(x) = n.parse::() { Ok(x) } else if n.parse::().is_ok() { - Err(JsonError::OutOfRangeU128) + Err(JsonError::OutOfRange(JsonOutOfRangeError::OutOfRangeU128)) } else { Err(JsonError::InvalidU128) } @@ -305,7 +318,10 @@ mod tests { let json = parse_json(r#"{"foo": -123}"#.as_bytes()).unwrap(); let err = json.u64("foo").unwrap_err(); - assert_eq!(err, JsonError::OutOfRangeU64); + assert_eq!( + err, + JsonError::OutOfRange(JsonOutOfRangeError::OutOfRangeU64) + ); let json = parse_json(r#"{"foo": "abcd"}"#.as_bytes()).unwrap(); let err = json.u64("foo").unwrap_err(); @@ -345,7 +361,10 @@ mod tests { let json = parse_json(r#"{"foo": "-123"}"#.as_bytes()).unwrap(); ////let val = json.u128("foo").ok().unwrap(); let err = json.u128("foo").unwrap_err(); - assert_eq!(err, JsonError::OutOfRangeU128); + assert_eq!( + err, + JsonError::OutOfRange(JsonOutOfRangeError::OutOfRangeU128) + ); let json = parse_json(r#"{"foo": 123}"#.as_bytes()).unwrap(); let err = json.u128("foo").unwrap_err(); @@ -427,11 +446,17 @@ mod tests { let json = JsonValue::from(-1f64); let err = JsonValue::parse_u8(&json).unwrap_err(); - assert_eq!(err, JsonError::OutOfRangeU8); + assert_eq!( + err, + JsonError::OutOfRange(JsonOutOfRangeError::OutOfRangeU8) + ); let json = JsonValue::from(256f64); let err = JsonValue::parse_u8(&json).unwrap_err(); - assert_eq!(err, JsonError::OutOfRangeU8); + assert_eq!( + err, + JsonError::OutOfRange(JsonOutOfRangeError::OutOfRangeU8) + ); let json = JsonValue::from("abcd".to_string()); let err = JsonValue::parse_u8(&json).unwrap_err(); diff --git a/src/lib.rs b/src/lib.rs index ffdd07e92..06423e4ea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -323,7 +323,6 @@ mod contract { let args: NEP141FtOnTransferArgs = parse_json(sdk::read_input().as_slice()) .sdk_unwrap() .try_into() - .map_err(|err| err) .sdk_unwrap(); if sdk::predecessor_account_id() == sdk::current_account_id() { From 289135f4f0be979db842a97cdb9acab28eccdbdf Mon Sep 17 00:00:00 2001 From: Evgeny Ukhanov Date: Fri, 9 Jul 2021 19:52:07 +0300 Subject: [PATCH 09/16] Extend errors types and tests --- src/json.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/json.rs b/src/json.rs index c1ca791d0..b66b2cf74 100644 --- a/src/json.rs +++ b/src/json.rs @@ -1,7 +1,5 @@ use super::prelude::*; -#[cfg(feature = "engine")] -use alloc::collections::BTreeMap; use core::convert::From; use rjson::{Array, Null, Object, Value}; #[cfg(test)] @@ -99,7 +97,7 @@ impl JsonValue { match v { JsonValue::Number(n) => { if *n < u8::MIN as f64 || *n > u8::MAX as f64 { - Err(JsonError::OutOfRange(JsonOutOfRangeError::OutOfRangeU64)) + Err(JsonError::OutOfRange(JsonOutOfRangeError::OutOfRangeU8)) } else { Ok(*n as u8) } @@ -323,6 +321,10 @@ mod tests { JsonError::OutOfRange(JsonOutOfRangeError::OutOfRangeU64) ); + // let json = parse_json(r#"{"foo": 12.3}"#.as_bytes()).unwrap(); + // let err = json.u64("foo").unwrap_err(); + // assert_eq!(err, JsonError::InvalidU64); + let json = parse_json(r#"{"foo": "abcd"}"#.as_bytes()).unwrap(); let err = json.u64("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidU64); @@ -359,7 +361,6 @@ mod tests { assert_eq!(val, 123); let json = parse_json(r#"{"foo": "-123"}"#.as_bytes()).unwrap(); - ////let val = json.u128("foo").ok().unwrap(); let err = json.u128("foo").unwrap_err(); assert_eq!( err, @@ -370,6 +371,14 @@ mod tests { let err = json.u128("foo").unwrap_err(); assert_eq!(err, JsonError::ExpectedStringGotNumber); + let json = parse_json(r#"{"foo": 12.3}"#.as_bytes()).unwrap(); + let err = json.u128("foo").unwrap_err(); + assert_eq!(err, JsonError::ExpectedStringGotNumber); + + let json = parse_json(r#"{"foo": "12.3"}"#.as_bytes()).unwrap(); + let err = json.u128("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidU128); + let json = parse_json(r#"{"foo": "abcd"}"#.as_bytes()).unwrap(); let err = json.u128("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidU128); @@ -421,6 +430,10 @@ mod tests { let err = json.bool("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidBool); + let json = parse_json(r#"{"foo": 12.3}"#.as_bytes()).unwrap(); + let err = json.bool("foo").unwrap_err(); + assert_eq!(err, JsonError::InvalidBool); + let json = parse_json(r#"{"foo": "abcd"}"#.as_bytes()).unwrap(); let err = json.bool("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidBool); From e5f4997c6c52fc894dc7c285af4d78d29f4f50c9 Mon Sep 17 00:00:00 2001 From: Evgeny Ukhanov Date: Fri, 9 Jul 2021 19:58:21 +0300 Subject: [PATCH 10/16] json: check overflow from i128 instead f64 --- src/json.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/json.rs b/src/json.rs index b66b2cf74..547cad159 100644 --- a/src/json.rs +++ b/src/json.rs @@ -61,7 +61,7 @@ impl JsonValue { JsonValue::Object(o) => match o.get(key).ok_or(JsonError::MissingValue)? { JsonValue::Number(n) => { // Upper bound is covered by the type limitation - if *n < u64::MIN as f64 { + if (*n as i128) < u64::MIN as i128 { Err(JsonError::OutOfRange(JsonOutOfRangeError::OutOfRangeU64)) } else { Ok(*n as u64) @@ -96,7 +96,7 @@ impl JsonValue { pub fn parse_u8(v: &JsonValue) -> Result { match v { JsonValue::Number(n) => { - if *n < u8::MIN as f64 || *n > u8::MAX as f64 { + if (*n as i128) < u8::MIN as i128 || (*n as i128) > u8::MAX as i128 { Err(JsonError::OutOfRange(JsonOutOfRangeError::OutOfRangeU8)) } else { Ok(*n as u8) From 2c33c38ec56842cb5d217ac15ef318263b416e9b Mon Sep 17 00:00:00 2001 From: Evgeny Ukhanov Date: Mon, 12 Jul 2021 16:16:35 +0300 Subject: [PATCH 11/16] Remove json array & test --- src/json.rs | 56 ----------------------------------------------------- 1 file changed, 56 deletions(-) diff --git a/src/json.rs b/src/json.rs index 547cad159..0454d5a3e 100644 --- a/src/json.rs +++ b/src/json.rs @@ -105,26 +105,6 @@ impl JsonValue { _ => Err(JsonError::InvalidU8), } } - - #[allow(dead_code)] - pub fn array(&self, key: &str, mut call: F) -> Result, JsonError> - where - F: FnMut(&JsonValue) -> Result, - { - match self { - JsonValue::Object(o) => match o.get(key).ok_or(JsonError::MissingValue)? { - JsonValue::Array(arr) => { - let mut res = vec![]; - for v in arr.iter() { - res.push(call(v)?); - } - Ok(res) - } - _ => Err(JsonError::InvalidArray), - }, - _ => Err(JsonError::NotJsonType), - } - } } impl AsRef<[u8]> for JsonError { @@ -475,40 +455,4 @@ mod tests { let err = JsonValue::parse_u8(&json).unwrap_err(); assert_eq!(err, JsonError::InvalidU8); } - - #[test] - fn test_json_type_array() { - let json = parse_json(r#"{"foo": [1, 3, 2, 100]}"#.as_bytes()).unwrap(); - let val = json.array("foo", JsonValue::parse_u8).ok().unwrap(); - assert_eq!(val, vec![1, 3, 2, 100]); - - let json = parse_json(r#"{"foo": []}"#.as_bytes()).unwrap(); - let val = json.array("foo", JsonValue::parse_u8).ok().unwrap(); - let res_data: Vec = vec![]; - assert_eq!(val, res_data); - - let json = parse_json(r#"{"foo": ["abcd"]}"#.as_bytes()).unwrap(); - let err = json.array("foo", JsonValue::parse_u8).unwrap_err(); - assert_eq!(err, JsonError::InvalidU8); - - let json = parse_json(r#"{"foo": "abcd"}"#.as_bytes()).unwrap(); - let err = json.array("foo", JsonValue::parse_u8).unwrap_err(); - assert_eq!(err, JsonError::InvalidArray); - - let json = parse_json(r#"{"foo": true}"#.as_bytes()).unwrap(); - let err = json.array("foo", JsonValue::parse_u8).unwrap_err(); - assert_eq!(err, JsonError::InvalidArray); - - let json = parse_json(r#"{"foo": {}}"#.as_bytes()).unwrap(); - let err = json.array("foo", JsonValue::parse_u8).unwrap_err(); - assert_eq!(err, JsonError::InvalidArray); - - let json = parse_json(r#"{"foo": null}"#.as_bytes()).unwrap(); - let err = json.array("foo", JsonValue::parse_u8).unwrap_err(); - assert_eq!(err, JsonError::InvalidArray); - - let json = JsonValue::Null; - let err = json.array("foo", JsonValue::parse_u8).unwrap_err(); - assert_eq!(err, JsonError::NotJsonType); - } } From f6d3325be9783a46d92ab3e2e69aca9b8565e46a Mon Sep 17 00:00:00 2001 From: Evgeny Ukhanov Date: Tue, 13 Jul 2021 00:25:25 +0300 Subject: [PATCH 12/16] extend json u64 test for f64 precision --- src/json.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/json.rs b/src/json.rs index 0454d5a3e..2b354eb30 100644 --- a/src/json.rs +++ b/src/json.rs @@ -294,6 +294,14 @@ mod tests { let val = json.u64("foo").ok().unwrap(); assert_eq!(val, 123); + let json = parse_json(r#"{"foo": 12.99}"#.as_bytes()).unwrap(); + let val = json.u64("foo").ok().unwrap(); + assert_eq!(val, 12); + + let json = parse_json(format!(r#"{{"foo": {} }}"#, u64::MAX).as_bytes()).unwrap(); + let val = json.u64("foo").ok().unwrap(); + assert_eq!(val, u64::MAX); + let json = parse_json(r#"{"foo": -123}"#.as_bytes()).unwrap(); let err = json.u64("foo").unwrap_err(); assert_eq!( From 4c33b20caf1bc800f7a40eb6e8fcbe5581d471cd Mon Sep 17 00:00:00 2001 From: Evgeny Ukhanov Date: Tue, 13 Jul 2021 00:26:21 +0300 Subject: [PATCH 13/16] json fix formatting --- src/json.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/json.rs b/src/json.rs index 2b354eb30..71025bddb 100644 --- a/src/json.rs +++ b/src/json.rs @@ -297,7 +297,7 @@ mod tests { let json = parse_json(r#"{"foo": 12.99}"#.as_bytes()).unwrap(); let val = json.u64("foo").ok().unwrap(); assert_eq!(val, 12); - + let json = parse_json(format!(r#"{{"foo": {} }}"#, u64::MAX).as_bytes()).unwrap(); let val = json.u64("foo").ok().unwrap(); assert_eq!(val, u64::MAX); From 60dc05f231de3c3b880af109407f21e669ce4825 Mon Sep 17 00:00:00 2001 From: Evgeny Ukhanov Date: Tue, 13 Jul 2021 08:55:35 +0300 Subject: [PATCH 14/16] json test parse_u64: u128 test and issue markers --- src/json.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/json.rs b/src/json.rs index 71025bddb..739542df3 100644 --- a/src/json.rs +++ b/src/json.rs @@ -294,11 +294,17 @@ mod tests { let val = json.u64("foo").ok().unwrap(); assert_eq!(val, 123); + let json = parse_json(format!(r#"{{"foo": {} }}"#, u64::MAX).as_bytes()).unwrap(); + let val = json.u64("foo").ok().unwrap(); + assert_eq!(val, u64::MAX); + let json = parse_json(r#"{"foo": 12.99}"#.as_bytes()).unwrap(); + // TODO [#176]: should fail since it is not a `u64` let val = json.u64("foo").ok().unwrap(); assert_eq!(val, 12); - let json = parse_json(format!(r#"{{"foo": {} }}"#, u64::MAX).as_bytes()).unwrap(); + let json = parse_json(format!(r#"{{"foo": {} }}"#, u128::MAX).as_bytes()).unwrap(); + // TODO [#176]: should fail since it is not a `u64` let val = json.u64("foo").ok().unwrap(); assert_eq!(val, u64::MAX); @@ -309,10 +315,6 @@ mod tests { JsonError::OutOfRange(JsonOutOfRangeError::OutOfRangeU64) ); - // let json = parse_json(r#"{"foo": 12.3}"#.as_bytes()).unwrap(); - // let err = json.u64("foo").unwrap_err(); - // assert_eq!(err, JsonError::InvalidU64); - let json = parse_json(r#"{"foo": "abcd"}"#.as_bytes()).unwrap(); let err = json.u64("foo").unwrap_err(); assert_eq!(err, JsonError::InvalidU64); From c83586335103e85ce24e167e1d3f974854c8dd2a Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Tue, 13 Jul 2021 12:28:34 +0000 Subject: [PATCH 15/16] JsonValue::u64 returns error for numbers greater than u64::MAX --- src/json.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/json.rs b/src/json.rs index 739542df3..f1e2dc7fc 100644 --- a/src/json.rs +++ b/src/json.rs @@ -60,9 +60,10 @@ impl JsonValue { match self { JsonValue::Object(o) => match o.get(key).ok_or(JsonError::MissingValue)? { JsonValue::Number(n) => { - // Upper bound is covered by the type limitation - if (*n as i128) < u64::MIN as i128 { + if n.is_sign_negative() || n.is_infinite() || n > &(u64::MAX as f64) { Err(JsonError::OutOfRange(JsonOutOfRangeError::OutOfRangeU64)) + } else if n.is_nan() { + Err(JsonError::InvalidU64) } else { Ok(*n as u64) } @@ -304,9 +305,11 @@ mod tests { assert_eq!(val, 12); let json = parse_json(format!(r#"{{"foo": {} }}"#, u128::MAX).as_bytes()).unwrap(); - // TODO [#176]: should fail since it is not a `u64` - let val = json.u64("foo").ok().unwrap(); - assert_eq!(val, u64::MAX); + let err = json.u64("foo").unwrap_err(); + assert_eq!( + err, + JsonError::OutOfRange(JsonOutOfRangeError::OutOfRangeU64) + ); let json = parse_json(r#"{"foo": -123}"#.as_bytes()).unwrap(); let err = json.u64("foo").unwrap_err(); From 34455f2bfe011ffb6d4395c9dd17ab289253a309 Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Tue, 13 Jul 2021 12:33:04 +0000 Subject: [PATCH 16/16] Avoid i128 cast --- src/json.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/json.rs b/src/json.rs index f1e2dc7fc..33202d64d 100644 --- a/src/json.rs +++ b/src/json.rs @@ -97,7 +97,7 @@ impl JsonValue { pub fn parse_u8(v: &JsonValue) -> Result { match v { JsonValue::Number(n) => { - if (*n as i128) < u8::MIN as i128 || (*n as i128) > u8::MAX as i128 { + if n.is_sign_negative() || n > &(u8::MAX as f64) { Err(JsonError::OutOfRange(JsonOutOfRangeError::OutOfRangeU8)) } else { Ok(*n as u8)