move debug string 官方实现代码解析
前段写了,move debug string的几种方法 后,有天看到,move 官方仓库有人提交了一个pr,added support to print UTF8-encoded std::string::String's via std::debug::print,感觉写得不错,深感上次说话太满,强中自有强中手,值得学习。
自己没做到的事情,别人给了好的解决方案,就要好好学习。 这里对pr的代码做一个解读。
我原来觉得这个改代码不好实现,主要基于move的内置类型,并没有string,如果在debug print的时候,不能有效的区分char 和byte 这么一个简单的逻辑。 这个pr从事实说明,我对于move 实现的代码,读得还不够,我的方式只是开了个小窗口,pr作者是理解代码的程度上做了修改。
- ("print", make_native_print(gas_params.print)), //原来的定义
+ ("print", make_native_print(gas_params.print, move_std_addr)), //修改过后的
在 make_native_print 函数中引入 move_std_addr ,后面在通过比较std地址和比较string typetag 名字来区分 char 和byte
#[cfg(feature = "testing")] //增加的类型判断
fn is_string_type(context: &NativeContext, ty: &Type, move_std_addr: AccountAddress) -> bool {
let ty_tag = match context.type_to_type_tag(ty) {
Ok(ty_tag) => ty_tag,
Err(_) => return false,
};
match ty_tag {
TypeTag::Struct(struct_tag) => {
struct_tag.address == move_std_addr
&& struct_tag.module.as_str().eq("string")
&& struct_tag.name.as_str().eq("String")
}
_ => false,
}
}
fn native_print(
gas_params: &PrintGasParameters,
_context: &mut NativeContext,
mut ty_args: Vec<Type>,
mut args: VecDeque<Value>,
move_std_addr: AccountAddress,){
let ty = ty_args.pop().unwrap();
match is_string_type(_context, &ty, move_std_addr) {
true => {
let r = pop_arg!(args, StructRef);
let field_ref = r
.borrow_field(0)? // borrows the 'bytes' field of the std::string::String struct
.value_as::<VectorRef>()?;
let bytes = field_ref.as_bytes_ref();
// This is safe because we guarantee the bytes to be utf8.
let str = unsafe { std::str::from_utf8_unchecked(bytes.as_slice()) };
//后面就可以打印
}
熟读代码还是很有必要。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!