1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use move_binary_format::errors::PartialVMResult;
use move_vm_runtime::native_functions::NativeContext;
use move_vm_types::{
gas_schedule::NativeCostIndex,
loaded_data::runtime_types::Type,
natives::function::{native_gas, NativeResult},
pop_arg,
values::{Value, VectorRef},
};
use std::collections::VecDeque;
pub fn native_check_utf8(
context: &mut NativeContext,
_ty_args: Vec<Type>,
mut args: VecDeque<Value>,
) -> PartialVMResult<NativeResult> {
debug_assert!(args.len() == 1);
let s_arg = pop_arg!(args, VectorRef);
let s_ref = s_arg.as_bytes_ref();
let ok = std::str::from_utf8(s_ref.as_slice()).is_ok();
let cost = native_gas(context.cost_table(), NativeCostIndex::PUSH_BACK, 1);
NativeResult::map_partial_vm_result_one(cost, Ok(Value::bool(ok)))
}
pub fn native_is_char_boundary(
context: &mut NativeContext,
_ty_args: Vec<Type>,
mut args: VecDeque<Value>,
) -> PartialVMResult<NativeResult> {
debug_assert!(args.len() == 2);
let i = pop_arg!(args, u64);
let s_arg = pop_arg!(args, VectorRef);
let s_ref = s_arg.as_bytes_ref();
let ok = unsafe {
std::str::from_utf8_unchecked(s_ref.as_slice()).is_char_boundary(i as usize)
};
let cost = native_gas(context.cost_table(), NativeCostIndex::PUSH_BACK, 1);
NativeResult::map_partial_vm_result_one(cost, Ok(Value::bool(ok)))
}
pub fn native_sub_string(
context: &mut NativeContext,
_ty_args: Vec<Type>,
mut args: VecDeque<Value>,
) -> PartialVMResult<NativeResult> {
debug_assert!(args.len() == 3);
let j = pop_arg!(args, u64) as usize;
let i = pop_arg!(args, u64) as usize;
let s_arg = pop_arg!(args, VectorRef);
let s_ref = s_arg.as_bytes_ref();
let s_str = unsafe {
std::str::from_utf8_unchecked(s_ref.as_slice())
};
let v = Value::vector_u8((&s_str[i..j]).as_bytes().iter().cloned());
let cost = native_gas(context.cost_table(), NativeCostIndex::PUSH_BACK, 1);
NativeResult::map_partial_vm_result_one(cost, Ok(v))
}
pub fn native_index_of(
context: &mut NativeContext,
_ty_args: Vec<Type>,
mut args: VecDeque<Value>,
) -> PartialVMResult<NativeResult> {
debug_assert!(args.len() == 2);
let r_arg = pop_arg!(args, VectorRef);
let r_ref = r_arg.as_bytes_ref();
let r_str = unsafe { std::str::from_utf8_unchecked(r_ref.as_slice()) };
let s_arg = pop_arg!(args, VectorRef);
let s_ref = s_arg.as_bytes_ref();
let s_str = unsafe { std::str::from_utf8_unchecked(s_ref.as_slice()) };
let pos = match s_str.find(r_str) {
Some(size) => size,
None => s_str.len(),
};
let cost = native_gas(context.cost_table(), NativeCostIndex::LENGTH, 1);
NativeResult::map_partial_vm_result_one(cost, Ok(Value::u64(pos as u64)))
}