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