@@ -310,8 +310,89 @@ Each field is as follows:
310310
311311Next, implement the decoding process.
312312
313- ``` diff
314313src/binary/module.rs
314+ ``` diff
315+ diff --git a/src/binary/module.rs b/src/binary/module.rs
316+ index 3e59d35..46db8dc 100644
317+ --- a/src/binary/module.rs
318+ +++ b/src/binary/module.rs
319+ @@ -3,7 +3,8 @@ use super::{
320+ opcode::Opcode,
321+ section::{Function, SectionCode},
322+ types::{
323+ - Export, ExportDesc, FuncType, FunctionLocal, Import, ImportDesc, Limits, Memory, ValueType,
324+ + Data, Export, ExportDesc, FuncType, FunctionLocal, Import, ImportDesc, Limits, Memory,
325+ + ValueType,
326+ },
327+ };
328+ use nom::{
329+ @@ -21,6 +22,7 @@ pub struct Module {
330+ pub magic: String,
331+ pub version: u32,
332+ pub memory_section: Option<Vec<Memory>>,
333+ + pub data_section: Option<Vec<Data>>,
334+ pub type_section: Option<Vec<FuncType>>,
335+ pub function_section: Option<Vec<u32>>,
336+ pub code_section: Option<Vec<Function>>,
337+ @@ -34,6 +36,7 @@ impl Default for Module {
338+ magic: "\0asm".to_string(),
339+ version: 1,
340+ memory_section: None,
341+ + data_section: None,
342+ type_section: None,
343+ function_section: None,
344+ code_section: None,
345+ @@ -75,6 +78,10 @@ impl Module {
346+ let (_, memory) = decode_memory_section(section_contents)?;
347+ module.memory_section = Some(vec![memory]);
348+ }
349+ + SectionCode::Data => {
350+ + let (_, data) = deocde_data_section(section_contents)?;
351+ + module.data_section = Some(data);
352+ + }
353+ SectionCode::Type => {
354+ let (_, types) = decode_type_section(section_contents)?;
355+ module.type_section = Some(types);
356+ @@ -95,7 +102,6 @@ impl Module {
357+ let (_, imports) = decode_import_section(section_contents)?;
358+ module.import_section = Some(imports);
359+ }
360+ - _ => todo!(),
361+ };
362+
363+ remaining = rest;
364+ @@ -286,6 +292,31 @@ fn decode_limits(input: &[u8]) -> IResult<&[u8], Limits> {
365+ Ok((input, Limits { min, max }))
366+ }
367+
368+ + fn decode_expr(input: &[u8]) -> IResult<&[u8], u32> {
369+ + let (input, _) = leb128_u32(input)?;
370+ + let (input, offset) = leb128_u32(input)?;
371+ + let (input, _) = leb128_u32(input)?;
372+ + Ok((input, offset))
373+ + }
374+ +
375+ + fn deocde_data_section(input: &[u8]) -> IResult<&[u8], Vec<Data>> {
376+ + let (mut input, count) = leb128_u32(input)?; // 1
377+ + let mut data = vec![];
378+ + for _ in 0..count {
379+ + let (rest, memory_index) = leb128_u32(input)?;
380+ + let (rest, offset) = decode_expr(rest)?; // 2
381+ + let (rest, size) = leb128_u32(rest)?; // 3
382+ + let (rest, init) = take(size)(rest)?; // 4
383+ + data.push(Data {
384+ + memory_index,
385+ + offset,
386+ + init: init.into(),
387+ + });
388+ + input = rest;
389+ + }
390+ + Ok((input, data))
391+ + }
392+ +
393+ fn decode_name(input: &[u8]) -> IResult<&[u8], String> {
394+ let (input, size) = leb128_u32(input)?;
395+ let (input, name) = take(size)(input)?;
315396```
316397
317398In the decoding process, the following steps are performed:
@@ -325,8 +406,70 @@ In the decoding process, the following steps are performed:
325406
326407Next, add tests to ensure the implementation is correct.
327408
328- ``` diff
329409src/binary/module.rs
410+ ``` diff
411+ diff --git a/src/binary/module.rs b/src/binary/module.rs
412+ index c0c1aff..40f20fd 100644
413+ --- a/src/binary/module.rs
414+ +++ b/src/binary/module.rs
415+ @@ -333,7 +333,7 @@ mod tests {
416+ module::Module,
417+ section::Function,
418+ types::{
419+ - Export, ExportDesc, FuncType, FunctionLocal, Import, ImportDesc, Limits, Memory,
420+ + Data, Export, ExportDesc, FuncType, FunctionLocal, Import, ImportDesc, Limits, Memory,
421+ ValueType,
422+ },
423+ };
424+ @@ -547,4 +547,48 @@ mod tests {
425+ }
426+ Ok(())
427+ }
428+ +
429+ + #[test]
430+ + fn decode_data() -> Result<()> {
431+ + let tests = vec![
432+ + (
433+ + "(module (memory 1) (data (i32.const 0) \"hello\"))",
434+ + vec![Data {
435+ + memory_index: 0,
436+ + offset: 0,
437+ + init: "hello".as_bytes().to_vec(),
438+ + }],
439+ + ),
440+ + (
441+ + "(module (memory 1) (data (i32.const 0) \"hello\") (data (i32.const 5) \"world\"))",
442+ + vec![
443+ + Data {
444+ + memory_index: 0,
445+ + offset: 0,
446+ + init: b"hello".into(),
447+ + },
448+ + Data {
449+ + memory_index: 0,
450+ + offset: 5,
451+ + init: b"world".into(),
452+ + },
453+ + ],
454+ + ),
455+ + ];
456+ +
457+ + for (wasm, data) in tests {
458+ + let module = Module::new(&wat::parse_str(wasm)?)?;
459+ + assert_eq!(
460+ + module,
461+ + Module {
462+ + memory_section: Some(vec![Memory {
463+ + limits: Limits { min: 1, max: None }
464+ + }]),
465+ + data_section: Some(data),
466+ + ..Default::default()
467+ + }
468+ + );
469+ + }
470+ + Ok(())
471+ + }
472+ }
330473```
331474
332475``` sh
@@ -349,15 +492,78 @@ test execution::runtime::tests::not_found_imported_func ... ok
349492
350493Now that we can retrieve memory data, we will proceed to place the data on the ` Runtime ` memory.
351494
352- ``` diff
353495src/execution/store.rs
496+ ``` diff
497+ diff --git a/src/execution/store.rs b/src/execution/store.rs
498+ index efadc19..cad96ca 100644
499+ --- a/src/execution/store.rs
500+ +++ b/src/execution/store.rs
501+ @@ -5,7 +5,7 @@ use crate::binary::{
502+ module::Module,
503+ types::{ExportDesc, FuncType, ImportDesc, ValueType},
504+ };
505+ - use anyhow::{bail, Result};
506+ + use anyhow::{anyhow, bail, Result};
507+
508+ pub const PAGE_SIZE: u32 = 65536; // 64Ki
509+
510+ @@ -146,6 +146,22 @@ impl Store {
511+ }
512+ }
513+
514+ + if let Some(ref sections) = module.data_section {
515+ + for data in sections {
516+ + let memory = memories
517+ + .get_mut(data.memory_index as usize)
518+ + .ok_or(anyhow!("not found memory"))?;
519+ +
520+ + let offset = data.offset as usize;
521+ + let init = &data.init;
522+ +
523+ + if offset + init.len() > memory.data.len() {
524+ + bail!("data is too large to fit in memory");
525+ + }
526+ + memory.data[offset..offset + init.len()].copy_from_slice(init);
527+ + }
528+ + }
529+ +
530+ Ok(Self {
531+ funcs,
532+ memories,
354533```
355534
356535The process is simple, copying the data from the ` Data Section ` to the specified location in memory.
357536Finally, add tests to ensure the implementation is correct.
358537
359- ``` diff
360538src/execution/store.rs
539+ ``` diff
540+ diff --git a/src/execution/store.rs b/src/execution/store.rs
541+ index cad96ca..1bb1192 100644
542+ --- a/src/execution/store.rs
543+ +++ b/src/execution/store.rs
544+ @@ -169,3 +169,32 @@ impl Store {
545+ })
546+ }
547+ }
548+ +
549+ + #[cfg(test)]
550+ + mod test {
551+ + use super::Store;
552+ + use crate::binary::module::Module;
553+ + use anyhow::Result;
554+ +
555+ + #[test]
556+ + fn init_memory() -> Result<()> {
557+ + let wasm = wat::parse_file("src/fixtures/memory.wat")?;
558+ + let module = Module::new(&wasm)?;
559+ + let store = Store::new(module)?;
560+ + assert_eq!(store.memories.len(), 1);
561+ + assert_eq!(store.memories[0].data.len(), 65536);
562+ + assert_eq!(&store.memories[0].data[0..5], b"hello");
563+ + assert_eq!(&store.memories[0].data[5..10], b"world");
564+ + Ok(())
565+ + }
566+ + }
361567```
362568
363569``` sh
0 commit comments