diff --git a/README.md b/README.md index fc39ba3..bfc90df 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ Project or files: │   └── quick_error ├── __ffi │   ├── c_export +│   ├── c_layout │   ├── cpp │   ├── jni │   └── live-reload-rust @@ -136,7 +137,7 @@ Project or files: ├── vec.rs └── while.rs -108 directories, 26 files +109 directories, 26 files ``` diff --git a/__ffi/c_layout/Cargo.lock b/__ffi/c_layout/Cargo.lock new file mode 100644 index 0000000..5f2e2cf --- /dev/null +++ b/__ffi/c_layout/Cargo.lock @@ -0,0 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "c_layout" +version = "0.1.0" diff --git a/__ffi/c_layout/Cargo.toml b/__ffi/c_layout/Cargo.toml new file mode 100644 index 0000000..921e22b --- /dev/null +++ b/__ffi/c_layout/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "c_layout" +version = "0.1.0" +authors = ["Hatter Jiang "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/__ffi/c_layout/README.md b/__ffi/c_layout/README.md new file mode 100644 index 0000000..699859d --- /dev/null +++ b/__ffi/c_layout/README.md @@ -0,0 +1,5 @@ + +reference: +https://users.rust-lang.org/t/read-into-struct/30972/3 +https://stackoverflow.com/questions/25410028/how-to-read-a-struct-from-a-file-in-rust + diff --git a/__ffi/c_layout/src/main.rs b/__ffi/c_layout/src/main.rs new file mode 100644 index 0000000..c5e7c35 --- /dev/null +++ b/__ffi/c_layout/src/main.rs @@ -0,0 +1,12 @@ +mod main_1; +mod main_2; +mod main_3; + +fn main() { + println!("{}", "-".repeat(88)); + main_1::run_main(); + println!("{}", "-".repeat(88)); + main_2::run_main(); + println!("{}", "-".repeat(88)); + main_3::run_main(); +} \ No newline at end of file diff --git a/__ffi/c_layout/src/main_1.rs b/__ffi/c_layout/src/main_1.rs new file mode 100644 index 0000000..7159cc1 --- /dev/null +++ b/__ffi/c_layout/src/main_1.rs @@ -0,0 +1,41 @@ +use std::io::Read; +use std::mem; +use std::slice; + +#[repr(C, packed)] +#[derive(Debug, Copy, Clone)] +struct Configuration { + item1: u8, + item2: u16, + item3: i32, + item4: [char; 8], +} + +const CONFIG_DATA: &[u8] = &[ + 0xfd, // u8 + 0xb4, 0x50, // u16 + 0x45, 0xcd, 0x3c, 0x15, // i32 + 0x71, 0x3c, 0x87, 0xff, // char + 0xe8, 0x5d, 0x20, 0xe7, // char + 0x5f, 0x38, 0x05, 0x4a, // char + 0xc4, 0x58, 0x8f, 0xdc, // char + 0x67, 0x1d, 0xb4, 0x64, // char + 0xf2, 0xc5, 0x2c, 0x15, // char + 0xd8, 0x9a, 0xae, 0x23, // char + 0x7d, 0xce, 0x4b, 0xeb, // char +]; + +pub fn run_main() { + let mut buffer = CONFIG_DATA; + + let mut config: Configuration = unsafe { mem::zeroed() }; + + let config_size = mem::size_of::(); + unsafe { + let config_slice = slice::from_raw_parts_mut(&mut config as *mut _ as *mut u8, config_size); + // `read_exact()` comes from `Read` impl for `&[u8]` + buffer.read_exact(config_slice).unwrap(); + } + + println!("Read structure: {:#?}", config); +} \ No newline at end of file diff --git a/__ffi/c_layout/src/main_2.rs b/__ffi/c_layout/src/main_2.rs new file mode 100644 index 0000000..6699cd3 --- /dev/null +++ b/__ffi/c_layout/src/main_2.rs @@ -0,0 +1,80 @@ +use std::io::{self, Read}; +use std::mem; +use std::slice; + +#[repr(C, packed)] +#[derive(Debug, Copy, Clone)] +struct Configuration { + item1: u8, + item2: u16, + item3: i32, + item4: [char; 8], +} + +const CONFIG_DATA: &[u8] = &[ + 0xfd, // u8 + 0xb4, 0x50, // u16 + 0x45, 0xcd, 0x3c, 0x15, // i32 + 0x71, 0x3c, 0x87, 0xff, // char + 0xe8, 0x5d, 0x20, 0xe7, // char + 0x5f, 0x38, 0x05, 0x4a, // char + 0xc4, 0x58, 0x8f, 0xdc, // char + 0x67, 0x1d, 0xb4, 0x64, // char + 0xf2, 0xc5, 0x2c, 0x15, // char + 0xd8, 0x9a, 0xae, 0x23, // char + 0x7d, 0xce, 0x4b, 0xeb, // char +]; + +fn read_struct(mut read: R) -> io::Result { + let num_bytes = ::std::mem::size_of::(); + unsafe { + let mut s = mem::zeroed();//mem::uninitialized(); + let buffer = slice::from_raw_parts_mut(&mut s as *mut T as *mut u8, num_bytes); + match read.read_exact(buffer) { + Ok(()) => Ok(s), + Err(e) => { + ::std::mem::forget(s); + Err(e) + } + } + } +} + +//// Here is a function that can read a struct (of a POD type) from a file: +// fn read_structs>(path: P) -> io::Result> { +// let path = path.as_ref(); +// let struct_size = ::std::mem::size_of::(); +// let num_bytes = std::fs::metadata(path)?.len() as usize; +// let num_structs = num_bytes / struct_size; +// let mut reader = std::io::BufReader::new(std::fs::File::open(path)?); +// let mut r = Vec::::with_capacity(num_structs); +// unsafe { +// let buffer = slice::from_raw_parts_mut(r.as_mut_ptr() as *mut u8, num_bytes); +// reader.read_exact(buffer)?; +// r.set_len(num_structs); +// } +// Ok(r) +// } + +//// If you want to read a sequence of structs from a file, you can execute read_struct multiple times or read all the file at once: +// fn read_structs>(path: P) -> io::Result> { +// let path = path.as_ref(); +// let struct_size = ::std::mem::size_of::(); +// let num_bytes = std::fs::metadata(path)?.len() as usize; +// let num_structs = num_bytes / struct_size; +// let mut reader = std::io::BufReader::new(std::fs::File::open(path)?); +// let mut r = Vec::::with_capacity(num_structs); +// unsafe { +// let buffer = slice::from_raw_parts_mut(r.as_mut_ptr() as *mut u8, num_bytes); +// reader.read_exact(buffer)?; +// r.set_len(num_structs); +// } +// Ok(r) +// } + + +pub fn run_main() { + let c: io::Result = read_struct(CONFIG_DATA); + + println!("{:#?}", c.unwrap()); +} \ No newline at end of file diff --git a/__ffi/c_layout/src/main_3.rs b/__ffi/c_layout/src/main_3.rs new file mode 100644 index 0000000..1509caa --- /dev/null +++ b/__ffi/c_layout/src/main_3.rs @@ -0,0 +1,43 @@ +use std::mem; +use std::io::{Read, Write, Result}; +use std::path::Path; +use std::fs::File; + +#[derive(Debug)] +#[repr(C)] +struct Header { + name: [u8; 4], + size: u32, + reserved: u64, +} + +fn parse>(path: P) -> Result<()> { + let mut file = File::open(path)?; + + let header: Header = { + let mut h = [0u8; mem::size_of::
()]; + file.read_exact(&mut h[..])?; + unsafe { mem::transmute(h) } + }; + + println!("{:#?}", header); + Ok(()) +} +fn write>(path: P, h: Header) -> Result<()> { + let mut file = File::create(path)?; + let bytes: [u8; mem::size_of::
()] = unsafe { mem::transmute(h) }; + file.write_all(&bytes)?; + + Ok(()) +} + +pub fn run_main() { + let h = Header { + name: [1,2,3,4], + size: 0xabcdef, + reserved: 0x0123456789abcdef, + }; + + write("/tmp/test.dat", h).unwrap(); + parse("/tmp/test.dat").unwrap(); +} \ No newline at end of file