Skip to content

Commit

Permalink
try changing to enum
Browse files Browse the repository at this point in the history
  • Loading branch information
igor-aptos committed Oct 10, 2024
1 parent 32dd58f commit fcc2f52
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 100 deletions.
94 changes: 50 additions & 44 deletions aptos-move/framework/move-stdlib/doc/cmp.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@



- [Struct `Ordering`](#0x1_cmp_Ordering)
- [Enum `Ordering`](#0x1_cmp_Ordering)
- [Constants](#@Constants_0)
- [Function `compare_impl`](#0x1_cmp_compare_impl)
- [Function `compare`](#0x1_cmp_compare)
- [Function `is_equal`](#0x1_cmp_is_equal)
- [Function `is_less_than`](#0x1_cmp_is_less_than)
Expand All @@ -22,89 +21,100 @@

<a id="0x1_cmp_Ordering"></a>

## Struct `Ordering`
## Enum `Ordering`



<pre><code><b>struct</b> <a href="cmp.md#0x1_cmp_Ordering">Ordering</a> <b>has</b> <b>copy</b>, drop
<pre><code>enum <a href="cmp.md#0x1_cmp_Ordering">Ordering</a> <b>has</b> <b>copy</b>, drop
</code></pre>



<details>
<summary>Variants</summary>


<details>
<summary>LessThan</summary>


<details>
<summary>Fields</summary>


<dl>
<dt>
<code>value: u8</code>
</dt>
<dd>

</dd>
</dl>


</details>

<a id="@Constants_0"></a>

## Constants
</details>

<details>
<summary>Equal</summary>

<a id="0x1_cmp_EQUAL"></a>

<details>
<summary>Fields</summary>


<pre><code><b>const</b> <a href="cmp.md#0x1_cmp_EQUAL">EQUAL</a>: u8 = 1;
</code></pre>
<dl>
</dl>


</details>

<a id="0x1_cmp_GREATER_THAN"></a>
</details>

<details>
<summary>GreaterThan</summary>


<pre><code><b>const</b> <a href="cmp.md#0x1_cmp_GREATER_THAN">GREATER_THAN</a>: u8 = 2;
</code></pre>
<details>
<summary>Fields</summary>


<dl>
</dl>

<a id="0x1_cmp_LESS_THAN"></a>

</details>

</details>

<pre><code><b>const</b> <a href="cmp.md#0x1_cmp_LESS_THAN">LESS_THAN</a>: u8 = 0;
</code></pre>
</details>

<a id="@Constants_0"></a>

## Constants

<a id="0x1_cmp_compare_impl"></a>

## Function `compare_impl`
<a id="0x1_cmp_EQUAL"></a>

As there are no signed values in move, all values are shifted by 1 up.
An int value:
1 iff both values are the same
0 iff first value is smaller than the second
2 iff first value is larger than the second


<pre><code><b>fun</b> <a href="cmp.md#0x1_cmp_compare_impl">compare_impl</a>&lt;T&gt;(first: &T, second: &T): u8
<pre><code><b>const</b> <a href="cmp.md#0x1_cmp_EQUAL">EQUAL</a>: u8 = 1;
</code></pre>



<details>
<summary>Implementation</summary>
<a id="0x1_cmp_GREATER_THAN"></a>



<pre><code><b>native</b> <b>fun</b> <a href="cmp.md#0x1_cmp_compare_impl">compare_impl</a>&lt;T&gt;(first: &T, second: &T): u8;
<pre><code><b>const</b> <a href="cmp.md#0x1_cmp_GREATER_THAN">GREATER_THAN</a>: u8 = 2;
</code></pre>



</details>
<a id="0x1_cmp_LESS_THAN"></a>



<pre><code><b>const</b> <a href="cmp.md#0x1_cmp_LESS_THAN">LESS_THAN</a>: u8 = 0;
</code></pre>



<a id="0x1_cmp_compare"></a>

Expand All @@ -121,11 +131,7 @@ An int value:
<summary>Implementation</summary>


<pre><code><b>public</b> <b>fun</b> <a href="cmp.md#0x1_cmp_compare">compare</a>&lt;T&gt;(first: &T, second: &T): <a href="cmp.md#0x1_cmp_Ordering">Ordering</a> {
<a href="cmp.md#0x1_cmp_Ordering">Ordering</a> {
value: <a href="cmp.md#0x1_cmp_compare_impl">compare_impl</a>(first, second),
}
}
<pre><code><b>public</b> <b>native</b> <b>fun</b> <a href="cmp.md#0x1_cmp_compare">compare</a>&lt;T&gt;(first: &T, second: &T): <a href="cmp.md#0x1_cmp_Ordering">Ordering</a>;
</code></pre>


Expand All @@ -148,7 +154,7 @@ An int value:


<pre><code><b>public</b> <b>fun</b> <a href="cmp.md#0x1_cmp_is_equal">is_equal</a>(self: &<a href="cmp.md#0x1_cmp_Ordering">Ordering</a>): bool {
self.value == <a href="cmp.md#0x1_cmp_EQUAL">EQUAL</a>
self is Ordering::Equal
}
</code></pre>

Expand All @@ -172,7 +178,7 @@ An int value:


<pre><code><b>public</b> <b>fun</b> <a href="cmp.md#0x1_cmp_is_less_than">is_less_than</a>(self: &<a href="cmp.md#0x1_cmp_Ordering">Ordering</a>): bool {
self.value == <a href="cmp.md#0x1_cmp_LESS_THAN">LESS_THAN</a>
self is Ordering::LessThan
}
</code></pre>

Expand All @@ -196,7 +202,7 @@ An int value:


<pre><code><b>public</b> <b>fun</b> <a href="cmp.md#0x1_cmp_is_less_or_equal">is_less_or_equal</a>(self: &<a href="cmp.md#0x1_cmp_Ordering">Ordering</a>): bool {
self.value != <a href="cmp.md#0x1_cmp_GREATER_THAN">GREATER_THAN</a>
!(self is Ordering::GreaterThan)
}
</code></pre>

Expand All @@ -220,7 +226,7 @@ An int value:


<pre><code><b>public</b> <b>fun</b> <a href="cmp.md#0x1_cmp_is_greater_than">is_greater_than</a>(self: &<a href="cmp.md#0x1_cmp_Ordering">Ordering</a>): bool {
self.value == <a href="cmp.md#0x1_cmp_GREATER_THAN">GREATER_THAN</a>
self is Ordering::GreaterThan
}
</code></pre>

Expand All @@ -244,7 +250,7 @@ An int value:


<pre><code><b>public</b> <b>fun</b> <a href="cmp.md#0x1_cmp_is__greater_or_equal">is__greater_or_equal</a>(self: &<a href="cmp.md#0x1_cmp_Ordering">Ordering</a>): bool {
self.value != <a href="cmp.md#0x1_cmp_LESS_THAN">LESS_THAN</a>
!(self is Ordering::LessThan)
}
</code></pre>

Expand Down
89 changes: 41 additions & 48 deletions aptos-move/framework/move-stdlib/sources/cmp.move
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,35 @@ module std::cmp {
const LESS_THAN: u8 = 0;
const GREATER_THAN: u8 = 2;

/// As there are no signed values in move, all values are shifted by 1 up.
/// An int value:
/// 1 iff both values are the same
/// 0 iff first value is smaller than the second
/// 2 iff first value is larger than the second
native fun compare_impl<T>(first: &T, second: &T): u8;

struct Ordering has copy, drop {
value: u8,
enum Ordering has copy, drop {
/// First value is less than the second value.
LessThan,
/// First value is equal to the second value.
Equal,
/// First value is greater than the second value.
GreaterThan,
}

public fun compare<T>(first: &T, second: &T): Ordering {
Ordering {
value: compare_impl(first, second),
}
}
public native fun compare<T>(first: &T, second: &T): Ordering;

public fun is_equal(self: &Ordering): bool {
self.value == EQUAL
self is Ordering::Equal
}

public fun is_less_than(self: &Ordering): bool {
self.value == LESS_THAN
self is Ordering::LessThan
}

public fun is_less_or_equal(self: &Ordering): bool {
self.value != GREATER_THAN
!(self is Ordering::GreaterThan)
}

public fun is_greater_than(self: &Ordering): bool {
self.value == GREATER_THAN
self is Ordering::GreaterThan
}

public fun is__greater_or_equal(self: &Ordering): bool {
self.value != LESS_THAN
!(self is Ordering::LessThan)
}

#[test_only]
Expand All @@ -46,11 +40,11 @@ module std::cmp {
field_2: u64,
}

// #[test_only]
// enum SomeEnum has drop {
// V1 { field_1: u64 },
// V2 { field_2: u64 },
// }
#[test_only]
enum SomeEnum has drop {
V1 { field_1: u64 },
V2 { field_2: u64 },
}

#[test]
fun test_compare_numbers() {
Expand All @@ -64,42 +58,41 @@ module std::cmp {
assert!(!is_less_than(&compare(&7, &5)), 7);
assert!(!is_less_or_equal(&compare(&7, &5)), 8);


// assert!(!compare(&1, &5).is_equal(), 0);
// assert!(compare(&1, &5).is_less_than(), 1);
// assert!(compare(&1, &5).is_less_or_equal(), 2);
// assert!(compare(&5, &5).is_equal(), 3);
// assert!(!compare(&5, &5).is_less_than(), 4);
// assert!(compare(&5, &5).is_less_or_equal(), 5);
// assert!(!compare(&7, &5).is_equal(), 6);
// assert!(!compare(&7, &5).is_less_than(), 7);
// assert!(!compare(&7, &5).is_less_or_equal(), 8);
assert!(!compare(&1, &5).is_equal(), 0);
assert!(compare(&1, &5).is_less_than(), 1);
assert!(compare(&1, &5).is_less_or_equal(), 2);
assert!(compare(&5, &5).is_equal(), 3);
assert!(!compare(&5, &5).is_less_than(), 4);
assert!(compare(&5, &5).is_less_or_equal(), 5);
assert!(!compare(&7, &5).is_equal(), 6);
assert!(!compare(&7, &5).is_less_than(), 7);
assert!(!compare(&7, &5).is_less_or_equal(), 8);
}

#[test]
fun test_compare_structs() {
assert!(compare(&SomeStruct { field_1: 1, field_2: 2}, &SomeStruct { field_1: 1, field_2: 3}).value == LESS_THAN, 0);
assert!(compare(&SomeStruct { field_1: 1, field_2: 2}, &SomeStruct { field_1: 1, field_2: 1}).value == GREATER_THAN, 1);
assert!(compare(&SomeStruct { field_1: 1, field_2: 2}, &SomeStruct { field_1: 1, field_2: 1}).value == GREATER_THAN, 2);
assert!(compare(&SomeStruct { field_1: 1, field_2: 2}, &SomeStruct { field_1: 1, field_2: 3}) is Ordering::LessThan, 0);
assert!(compare(&SomeStruct { field_1: 1, field_2: 2}, &SomeStruct { field_1: 1, field_2: 1}) is Ordering::GreaterThan, 1);
assert!(compare(&SomeStruct { field_1: 1, field_2: 2}, &SomeStruct { field_1: 1, field_2: 1}) is Ordering::GreaterThan, 2);
}

#[test]
fun test_compare_vector_of_structs() {
assert!(compare(&vector[SomeStruct { field_1: 1, field_2: 2}, SomeStruct { field_1: 3, field_2: 4}], &vector[SomeStruct { field_1: 1, field_2: 3}]).value == LESS_THAN, 0);
assert!(compare(&vector[SomeStruct { field_1: 1, field_2: 2}, SomeStruct { field_1: 3, field_2: 4}], &vector[SomeStruct { field_1: 1, field_2: 2}, SomeStruct { field_1: 1, field_2: 3}]).value == GREATER_THAN, 1);
assert!(compare(&vector[SomeStruct { field_1: 1, field_2: 2}, SomeStruct { field_1: 3, field_2: 4}], &vector[SomeStruct { field_1: 1, field_2: 3}]) is Ordering::LessThan, 0);
assert!(compare(&vector[SomeStruct { field_1: 1, field_2: 2}, SomeStruct { field_1: 3, field_2: 4}], &vector[SomeStruct { field_1: 1, field_2: 2}, SomeStruct { field_1: 1, field_2: 3}]) is Ordering::GreaterThan, 1);
}

// #[test]
// fun test_compare_enums() {
// assert!(compare(&SomeEnum::V1 { field_1: 6}, &SomeEnum::V2 { field_2: 1}).value == LESS_THAN, 0);
// assert!(compare(&SomeEnum::V1 { field_1: 6}, &SomeEnum::V2 { field_2: 8}).value == LESS_THAN, 0);
// assert!(compare(&SomeEnum::V1 { field_1: 6}, &SomeEnum::V1 { field_1: 5}).value == GREATER_THAN, 1);
// }
#[test]
fun test_compare_enums() {
assert!(compare(&SomeEnum::V1 { field_1: 6}, &SomeEnum::V2 { field_2: 1}) is Ordering::LessThan, 0);
assert!(compare(&SomeEnum::V1 { field_1: 6}, &SomeEnum::V2 { field_2: 8}) is Ordering::LessThan, 0);
assert!(compare(&SomeEnum::V1 { field_1: 6}, &SomeEnum::V1 { field_1: 5}) is Ordering::GreaterThan, 1);
}

#[test]
fun test_compare_vectors() {
assert!(compare(&vector[1, 2, 3], &vector[5] ).value == LESS_THAN, 0);
assert!(compare(&vector[1, 2, 3], &vector[5, 6, 7]).value == LESS_THAN, 1);
assert!(compare(&vector[1, 2, 3], &vector[1, 2, 7]).value == LESS_THAN, 2);
assert!(compare(&vector[1, 2, 3], &vector[5] ) is Ordering::LessThan, 0);
assert!(compare(&vector[1, 2, 3], &vector[5, 6, 7]) is Ordering::LessThan, 1);
assert!(compare(&vector[1, 2, 3], &vector[1, 2, 7]) is Ordering::LessThan, 2);
}
}
20 changes: 12 additions & 8 deletions aptos-move/framework/move-stdlib/src/natives/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use aptos_native_interface::{
use move_core_types::vm_status::StatusCode;
use move_vm_runtime::native_functions::NativeFunction;
use move_vm_types::{
loaded_data::runtime_types::Type, natives::function::PartialVMError, values::Value,
loaded_data::runtime_types::Type, natives::function::PartialVMError, values::{Struct, Value},
};
use smallvec::{smallvec, SmallVec};
use std::collections::VecDeque;
Expand All @@ -29,13 +29,17 @@ use std::collections::VecDeque;
// create a `&str` view on the bytes without a copy. Once we have this
// view, we can call ut8 functions like length, substring, etc.

const ORDERING_LESS_THAN_VARIANT: u16 = 0;
const ORDERING_EQUAL_VARIANT: u16 = 1;
const ORDERING_GREATER_THAN_VARIANT: u16 = 2;

/***************************************************************************************************
* native fun internal_check_utf8
*
* gas cost: base_cost + unit_cost * length_in_bytes
*
**************************************************************************************************/
fn native_compare_impl(
fn native_compare(
context: &mut SafeNativeContext,
_ty_args: Vec<Type>,
args: VecDeque<Value>,
Expand All @@ -54,13 +58,13 @@ fn native_compare_impl(
context.charge(cost)?;

Check warning on line 58 in aptos-move/framework/move-stdlib/src/natives/cmp.rs

View check run for this annotation

Codecov / codecov/patch

aptos-move/framework/move-stdlib/src/natives/cmp.rs#L42-L58

Added lines #L42 - L58 were not covered by tests

let ordering = args[0].compare(&args[1])?;
let result = match ordering {
std::cmp::Ordering::Less => 0,
std::cmp::Ordering::Equal => 1,
std::cmp::Ordering::Greater => 2,
let ordering_move_variant = match ordering {
std::cmp::Ordering::Less => ORDERING_LESS_THAN_VARIANT,
std::cmp::Ordering::Equal => ORDERING_EQUAL_VARIANT,
std::cmp::Ordering::Greater => ORDERING_GREATER_THAN_VARIANT,

Check warning on line 64 in aptos-move/framework/move-stdlib/src/natives/cmp.rs

View check run for this annotation

Codecov / codecov/patch

aptos-move/framework/move-stdlib/src/natives/cmp.rs#L60-L64

Added lines #L60 - L64 were not covered by tests
};

Ok(smallvec![Value::u8(result)])
Ok(smallvec![Value::struct_(Struct::pack(vec![Value::u16(ordering_move_variant)]))])
}

Check warning on line 68 in aptos-move/framework/move-stdlib/src/natives/cmp.rs

View check run for this annotation

Codecov / codecov/patch

aptos-move/framework/move-stdlib/src/natives/cmp.rs#L67-L68

Added lines #L67 - L68 were not covered by tests

/***************************************************************************************************
Expand All @@ -69,7 +73,7 @@ fn native_compare_impl(
pub fn make_all(
builder: &SafeNativeBuilder,
) -> impl Iterator<Item = (String, NativeFunction)> + '_ {
let natives = [("compare_impl", native_compare_impl as RawSafeNative)];
let natives = [("compare", native_compare as RawSafeNative)];

builder.make_named_natives(natives)
}

0 comments on commit fcc2f52

Please sign in to comment.