1 use crate::MemoryIndex; 2 use crate::component::Transcode; 3 use crate::fact::core_types::CoreTypes; 4 use crate::prelude::*; 5 use wasm_encoder::{EntityType, ValType}; 6 7 #[derive(Copy, Clone, Hash, Eq, PartialEq)] 8 pub struct Transcoder { 9 pub from_memory: MemoryIndex, 10 pub from_memory64: bool, 11 pub to_memory: MemoryIndex, 12 pub to_memory64: bool, 13 pub op: Transcode, 14 } 15 16 impl Transcoder { name(&self) -> String17 pub fn name(&self) -> String { 18 format!( 19 "{} (mem{} => mem{})", 20 self.op.desc(), 21 self.from_memory.as_u32(), 22 self.to_memory.as_u32(), 23 ) 24 } 25 ty(&self, types: &mut CoreTypes) -> EntityType26 pub fn ty(&self, types: &mut CoreTypes) -> EntityType { 27 let from_ptr = if self.from_memory64 { 28 ValType::I64 29 } else { 30 ValType::I32 31 }; 32 let to_ptr = if self.to_memory64 { 33 ValType::I64 34 } else { 35 ValType::I32 36 }; 37 38 let ty = match self.op { 39 // These direct transcodings take the source pointer, the source 40 // code units, and the destination pointer. 41 // 42 // The memories being copied between are part of each intrinsic and 43 // the destination code units are the same as the source. 44 // Note that the pointers are dynamically guaranteed to be aligned 45 // and in-bounds for the code units length as defined by the string 46 // encoding. 47 Transcode::Copy(_) | Transcode::Latin1ToUtf16 => { 48 types.function(&[from_ptr, from_ptr, to_ptr], &[]) 49 } 50 51 // Transcoding from utf8 to utf16 takes the from ptr/len as well as 52 // a destination. The destination is valid for len*2 bytes. The 53 // return value is how many code units were written to the 54 // destination. 55 Transcode::Utf8ToUtf16 => types.function(&[from_ptr, from_ptr, to_ptr], &[to_ptr]), 56 57 // Transcoding to utf8 as a smaller format takes all the parameters 58 // and returns the amount of space consumed in the src/destination 59 Transcode::Utf16ToUtf8 | Transcode::Latin1ToUtf8 => { 60 types.function(&[from_ptr, from_ptr, to_ptr, to_ptr], &[from_ptr, to_ptr]) 61 } 62 63 // The return type is a tagged length which indicates which was 64 // used 65 Transcode::Utf16ToCompactProbablyUtf16 => { 66 types.function(&[from_ptr, from_ptr, to_ptr], &[to_ptr]) 67 } 68 69 // The initial step of transcoding from a fixed format to a compact 70 // format. Takes the ptr/len of the source the destination 71 // pointer. The destination length is implicitly the same. Returns 72 // how many code units were consumed in the source, which is also 73 // how many bytes were written to the destination. 74 Transcode::Utf8ToLatin1 | Transcode::Utf16ToLatin1 => { 75 types.function(&[from_ptr, from_ptr, to_ptr], &[from_ptr, to_ptr]) 76 } 77 78 // The final step of transcoding to a compact format when the fixed 79 // transcode has failed. This takes the ptr/len of the source that's 80 // remaining to transcode. Then this takes the destination ptr/len 81 // as well as the destination bytes written so far with latin1. 82 // Finally this returns the number of code units written to the 83 // destination. 84 Transcode::Utf8ToCompactUtf16 | Transcode::Utf16ToCompactUtf16 => { 85 types.function(&[from_ptr, from_ptr, to_ptr, to_ptr, to_ptr], &[to_ptr]) 86 } 87 }; 88 EntityType::Function(ty) 89 } 90 } 91