use core::{cmp::Ordering, fmt};
use const_fn::const_fn;
use evil_janet::{
JANET_CURRENT_CONFIG_BITS, JANET_VERSION_MAJOR, JANET_VERSION_MINOR, JANET_VERSION_PATCH,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct JanetBuildConfig {
version: JanetVersion,
bits: u32,
}
impl JanetBuildConfig {
#[inline]
pub const fn current() -> Self {
Self {
version: JanetVersion::current(),
bits: JANET_CURRENT_CONFIG_BITS,
}
}
#[inline]
pub const fn custom(major: u32, minor: u32, patch: u32, bits: u32) -> Self {
Self {
version: JanetVersion::custom(major, minor, patch),
bits,
}
}
#[inline]
pub const fn version(&self) -> JanetVersion {
self.version
}
#[inline]
#[const_fn("1.46")]
pub const fn is_single_threaded(&self) -> bool {
match self.bits {
0 | 1 => false,
2 | 3 => true,
_ => false,
}
}
#[inline]
#[const_fn("1.46")]
pub const fn is_nanbox(&self) -> bool {
match self.bits {
0 | 2 => false,
1 | 3 => true,
_ => false,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct JanetVersion {
major: u32,
minor: u32,
patch: u32,
}
impl JanetVersion {
#[inline]
pub const fn current() -> Self {
Self {
major: JANET_VERSION_MAJOR,
minor: JANET_VERSION_MINOR,
patch: JANET_VERSION_PATCH,
}
}
#[inline]
pub const fn custom(major: u32, minor: u32, patch: u32) -> Self {
Self {
major,
minor,
patch,
}
}
#[inline]
pub const fn major(&self) -> u32 {
self.major
}
#[inline]
pub const fn minor(&self) -> u32 {
self.minor
}
#[inline]
pub const fn patch(&self) -> u32 {
self.patch
}
}
impl fmt::Display for JanetVersion {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Janet {}.{}.{}", self.major, self.minor, self.patch)
}
}
impl PartialEq<(u32, u32, u32)> for JanetVersion {
#[inline]
fn eq(&self, (major, minor, patch): &(u32, u32, u32)) -> bool {
self.major.eq(major) && self.minor.eq(minor) && self.patch.eq(patch)
}
}
impl PartialEq<[u32; 3]> for JanetVersion {
#[inline]
fn eq(&self, [major, minor, patch]: &[u32; 3]) -> bool {
self.major.eq(major) && self.minor.eq(minor) && self.patch.eq(patch)
}
}
impl PartialEq<&str> for JanetVersion {
#[cfg_attr(feature = "inline-more", inline)]
fn eq(&self, other: &&str) -> bool {
if other.split('.').count() > 3 {
false
} else {
other
.split('.')
.map(|s| s.parse::<u32>())
.take(3)
.zip([self.major, self.minor, self.patch].iter())
.map(|(o, s)| o.unwrap_or(u32::MAX).eq(s))
.all(core::convert::identity)
}
}
}
impl PartialOrd for JanetVersion {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match self.major.cmp(&other.major) {
Ordering::Equal => match self.minor.cmp(&other.minor) {
Ordering::Equal => Some(self.patch.cmp(&other.patch)),
x => Some(x),
},
x => Some(x),
}
}
}
impl PartialOrd<(u32, u32, u32)> for JanetVersion {
#[cfg_attr(feature = "inline-more", inline)]
fn partial_cmp(&self, (major, minor, patch): &(u32, u32, u32)) -> Option<Ordering> {
match self.major.cmp(major) {
Ordering::Equal => match self.minor.cmp(minor) {
Ordering::Equal => Some(self.patch.cmp(patch)),
x => Some(x),
},
x => Some(x),
}
}
}
impl PartialOrd<[u32; 3]> for JanetVersion {
#[cfg_attr(feature = "inline-more", inline)]
fn partial_cmp(&self, [major, minor, patch]: &[u32; 3]) -> Option<Ordering> {
match self.major.cmp(major) {
Ordering::Equal => match self.minor.cmp(minor) {
Ordering::Equal => Some(self.patch.cmp(patch)),
x => Some(x),
},
x => Some(x),
}
}
}
impl PartialOrd<&str> for JanetVersion {
#[cfg_attr(feature = "inline-more", inline)]
fn partial_cmp(&self, other: &&str) -> Option<Ordering> {
let [major, minor, patch] = {
let iter = other.split('.');
if iter.clone().count() > 3 {
return None;
}
let mut arr = [0; 3];
for (index, elem) in iter.map(|s| s.parse().ok()).enumerate() {
arr[index] = elem?;
}
arr
};
match self.major.cmp(&major) {
Ordering::Equal => match self.minor.cmp(&minor) {
Ordering::Equal => Some(self.patch.cmp(&patch)),
x => Some(x),
},
x => Some(x),
}
}
}
impl Ord for JanetVersion {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
match self.major.cmp(&other.major) {
Ordering::Equal => match self.minor.cmp(&other.minor) {
Ordering::Equal => self.patch.cmp(&other.patch),
x => x,
},
x => x,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn janet_version_ord() {
assert_eq!(
Ordering::Equal,
JanetVersion::custom(1, 1, 1).cmp(&JanetVersion::custom(1, 1, 1))
);
assert_eq!(
Ordering::Equal,
JanetVersion::custom(1, 2, 1).cmp(&JanetVersion::custom(1, 2, 1))
);
assert_eq!(
Ordering::Less,
JanetVersion::custom(1, 1, 1).cmp(&JanetVersion::custom(2, 1, 1))
);
assert_eq!(
Ordering::Less,
JanetVersion::custom(1, 1, 1).cmp(&JanetVersion::custom(1, 2, 1))
);
assert_eq!(
Ordering::Less,
JanetVersion::custom(1, 1, 1).cmp(&JanetVersion::custom(1, 1, 2))
);
assert_eq!(
Ordering::Greater,
JanetVersion::custom(2, 1, 1).cmp(&JanetVersion::custom(1, 1, 1))
);
assert_eq!(
Ordering::Greater,
JanetVersion::custom(1, 2, 1).cmp(&JanetVersion::custom(1, 1, 1))
);
assert_eq!(
Ordering::Greater,
JanetVersion::custom(1, 1, 2).cmp(&JanetVersion::custom(1, 1, 1))
);
}
#[test]
fn version_eq_tuple() {
assert!(JanetVersion::custom(1, 10, 0) == (1, 10, 0));
assert!(JanetVersion::custom(0, 1, 9) == (0, 1, 9));
}
#[test]
fn version_eq_str() {
assert!(JanetVersion::custom(1, 10, 0) == "1.10.0");
assert!(JanetVersion::custom(0, 1, 9) == "0.1.9");
}
#[test]
fn version_ord_tuple() {
assert_eq!(
Some(Ordering::Equal),
JanetVersion::custom(1, 1, 1).partial_cmp(&(1, 1, 1))
);
assert_eq!(
Some(Ordering::Equal),
JanetVersion::custom(1, 2, 1).partial_cmp(&(1, 2, 1))
);
assert_eq!(
Some(Ordering::Less),
JanetVersion::custom(1, 1, 1).partial_cmp(&(2, 1, 1))
);
assert_eq!(
Some(Ordering::Less),
JanetVersion::custom(1, 1, 1).partial_cmp(&(1, 2, 1))
);
assert_eq!(
Some(Ordering::Less),
JanetVersion::custom(1, 1, 1).partial_cmp(&(1, 1, 2))
);
assert_eq!(
Some(Ordering::Greater),
JanetVersion::custom(2, 1, 1).partial_cmp(&(1, 1, 1))
);
assert_eq!(
Some(Ordering::Greater),
JanetVersion::custom(1, 2, 1).partial_cmp(&(1, 1, 1))
);
assert_eq!(
Some(Ordering::Greater),
JanetVersion::custom(1, 1, 2).partial_cmp(&(1, 1, 1))
);
}
#[test]
fn version_ord_str() {
assert_eq!(
Some(Ordering::Equal),
JanetVersion::custom(1, 1, 1).partial_cmp(&"1.1.1")
);
assert_eq!(
Some(Ordering::Equal),
JanetVersion::custom(1, 2, 1).partial_cmp(&"1.2.1")
);
assert_eq!(
Some(Ordering::Less),
JanetVersion::custom(1, 1, 1).partial_cmp(&"2.1.1")
);
assert_eq!(
Some(Ordering::Less),
JanetVersion::custom(1, 1, 1).partial_cmp(&"1.2.1")
);
assert_eq!(
Some(Ordering::Less),
JanetVersion::custom(1, 1, 1).partial_cmp(&"1.1.2")
);
assert_eq!(
Some(Ordering::Greater),
JanetVersion::custom(2, 1, 1).partial_cmp(&"1.1.1")
);
assert_eq!(
Some(Ordering::Greater),
JanetVersion::custom(1, 2, 1).partial_cmp(&"1.1.1")
);
assert_eq!(
Some(Ordering::Greater),
JanetVersion::custom(1, 1, 2).partial_cmp(&"1.1.1")
);
assert_eq!(None, JanetVersion::custom(1, 1, 2).partial_cmp(&""));
assert_eq!(
None,
JanetVersion::custom(1, 1, 2).partial_cmp(&"version go brr")
);
assert_eq!(None, JanetVersion::custom(1, 1, 2).partial_cmp(&"1.1.1.1"));
}
#[test]
fn config_bits() {
let test0 = JanetBuildConfig::custom(0, 0, 0, 0);
let test1 = JanetBuildConfig::custom(0, 0, 0, 1);
let test2 = JanetBuildConfig::custom(0, 0, 0, 2);
let test3 = JanetBuildConfig::custom(0, 0, 0, 3);
assert!(!test0.is_nanbox());
assert!(!test0.is_single_threaded());
assert!(test1.is_nanbox());
assert!(!test1.is_single_threaded());
assert!(!test2.is_nanbox());
assert!(test2.is_single_threaded());
assert!(test3.is_nanbox());
assert!(test3.is_single_threaded());
}
}