From 42e5a1be64694c2518086274aee0437ca25dc8d0 Mon Sep 17 00:00:00 2001 From: GrayJack Date: Wed, 4 Dec 2024 23:41:14 -0300 Subject: [PATCH] feat: Make conversion from `Janet` to `i64`, `u64`, `usize`and `isize` accept when Janet is String --- CHANGELOG.md | 2 ++ src/types.rs | 27 ++++++++++++++++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 620fa6abab..1ad59e01b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to the library should be put here - **Breaking** Refactor: Use `usize` for length/index/capacity in collections - **Breaking** Refactor: Make `IsJanetAbstract` an unsafe trait - **Breaking** Feat: Make `amalgation` feature enabled by default +- **Breaking** Feat: Make `#[janet_fn]` maintain the high-level function in scope - Feat: Add `Janet::dynamic_from_cstr` constructor - Feat: Add `JanetArgs::get_value` and `JanetArgs::get_tagged` trait methods - Feat: Add `JanetArgs::get_or_default` trait method @@ -32,6 +33,7 @@ All notable changes to the library should be put here - Feat: Add conversion from `Janet` to `isize` and `usize` - Feat: Add conversion from `isize`/`usize` to `Janet` - Feat: Make conversion from `Janet` to `i64` and `u64` accept when Janet is Number +- Feat: Make conversion from `Janet` to `i64`, `u64`, `usize`, `isize` accept when Janet is String - Perf: Avoid allocation in `Janet::dynamic` if the passed argument is already null terminated - Refactor: Use default implementation on `JanetArgs` trait for most methods - Refactor: Simplify `jpanic!` macro diff --git a/src/types.rs b/src/types.rs index 5cc0ae5f96..7af399a777 100644 --- a/src/types.rs +++ b/src/types.rs @@ -8,6 +8,7 @@ use core::{ cmp::Ordering, ffi::{CStr, c_char}, fmt::{self, Display, Write}, + num::ParseIntError, }; #[cfg(not(feature = "std"))] @@ -88,7 +89,7 @@ pub trait DeepEq { /// /// This error only occurs when the [`Janet`] and the type it was being converted doesn't /// match. -#[derive(Debug, PartialEq, PartialOrd, Default)] +#[derive(Debug, PartialEq, Default)] #[non_exhaustive] pub enum JanetConversionError { /// Mismatched types. @@ -101,6 +102,7 @@ pub enum JanetConversionError { InvalidUInt32(f64), InvalidSSize(f64), InvalidUSize(f64), + IntFromStr(ParseIntError), #[default] Other, } @@ -115,6 +117,12 @@ impl JanetConversionError { } } +impl From for JanetConversionError { + fn from(value: ParseIntError) -> Self { + Self::IntFromStr(value) + } +} + #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl error::Error for JanetConversionError {} @@ -146,6 +154,9 @@ impl Display for JanetConversionError { }, Self::InvalidSSize(bad_value) => write!(f, "Expected signed size, got {bad_value}"), Self::InvalidUSize(bad_value) => write!(f, "Expected unsigned size, got {bad_value}"), + Self::IntFromStr(err) => { + write!(f, "Error while converting integer from string: {err}") + }, Self::Other => f.pad("Error converting Janet to concrete type"), } } @@ -936,8 +947,9 @@ impl TryFrom for isize { Err(JanetConversionError::InvalidSSize(x)) } }, + TaggedJanet::String(s) => Ok(s.trim().to_str_lossy().parse::()?), got => Err(JanetConversionError::multi_wrong_kind( - vec![JanetType::Abstract, JanetType::Number], + vec![JanetType::Abstract, JanetType::String, JanetType::Number], got.kind(), )), } @@ -977,8 +989,9 @@ impl TryFrom for usize { Err(JanetConversionError::InvalidUSize(x)) } }, + TaggedJanet::String(s) => Ok(s.trim().to_str_lossy().parse::()?), got => Err(JanetConversionError::multi_wrong_kind( - vec![JanetType::Abstract, JanetType::Number], + vec![JanetType::Abstract, JanetType::String, JanetType::Number], got.kind(), )), } @@ -1004,7 +1017,6 @@ impl TryFrom for i64 { #[inline] fn try_from(value: Janet) -> Result { - // FIXME: To have parity with C janet semantics, we have to accept JanetString as well match value.unwrap() { TaggedJanet::Abstract(x) => Ok(x.into_inner()?), TaggedJanet::Number(x) => { @@ -1014,8 +1026,9 @@ impl TryFrom for i64 { Err(JanetConversionError::InvalidInt32(x)) } }, + TaggedJanet::String(s) => Ok(s.trim().to_str_lossy().parse::()?), got => Err(JanetConversionError::multi_wrong_kind( - vec![JanetType::Abstract, JanetType::Number], + vec![JanetType::Abstract, JanetType::String, JanetType::Number], got.kind(), )), } @@ -1041,7 +1054,6 @@ impl TryFrom for u64 { #[inline] fn try_from(value: Janet) -> Result { - // FIXME: To have parity with C janet semantics, we have to accept JanetString as well match value.unwrap() { TaggedJanet::Abstract(x) => Ok(x.into_inner()?), TaggedJanet::Number(x) => { @@ -1051,8 +1063,9 @@ impl TryFrom for u64 { Err(JanetConversionError::InvalidUInt32(x)) } }, + TaggedJanet::String(s) => Ok(s.trim().to_str_lossy().parse::()?), got => Err(JanetConversionError::multi_wrong_kind( - vec![JanetType::Abstract, JanetType::Number], + vec![JanetType::Abstract, JanetType::String, JanetType::Number], got.kind(), )), }