use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
use std::mem;
#[derive(Debug, Clone)]
pub struct DnaStrMember {
pub mem_type: String,
pub mem_name: String,
}
impl DnaStrMember {
pub fn new(mem_type: String, mem_name: String) -> Self {
DnaStrMember {
mem_type: mem_type,
mem_name: mem_name,
}
}
}
#[derive(Debug)]
pub struct DnaStrC {
pub sdna_nr: u32,
pub members: Vec<DnaStrMember>,
}
impl DnaStrC {
pub fn new(sdna_nr: u32, members: Vec<DnaStrMember>) -> Self {
DnaStrC {
sdna_nr: sdna_nr,
members: members,
}
}
}
fn decode_blender_header(print_dna: bool, header: &[u8], version: &mut u32) -> bool {
match header[0] as char {
'B' => {
if print_dna {
print!("B")
}
}
_ => return false,
}
match header[1] as char {
'L' => {
if print_dna {
print!("L")
}
}
_ => return false,
}
match header[2] as char {
'E' => {
if print_dna {
print!("E")
}
}
_ => return false,
}
match header[3] as char {
'N' => {
if print_dna {
print!("N")
}
}
_ => return false,
}
match header[4] as char {
'D' => {
if print_dna {
print!("D")
}
}
_ => return false,
}
match header[5] as char {
'E' => {
if print_dna {
print!("E")
}
}
_ => return false,
}
match header[6] as char {
'R' => {
if print_dna {
print!("R")
}
}
_ => return false,
}
match header[7] as char {
'_' => {
if print_dna {
print!("_")
}
}
'-' => {
if print_dna {
print!("-")
}
}
_ => return false,
}
match header[8] as char {
'v' => {
if print_dna {
print!("v")
}
}
'V' => {
if print_dna {
print!("V")
}
}
_ => return false,
}
for i in 9..12 {
if header[i].is_ascii_digit() {
if print_dna {
print!("{:?}", (header[i] as char).to_digit(10).unwrap())
};
} else {
return false;
}
}
if print_dna {
print!("\n");
}
let last3c = vec![header[9], header[10], header[11]];
let version_str = String::from_utf8(last3c).unwrap();
*version = version_str.parse::<u32>().unwrap();
true
}
fn make_id(code: &[u8]) -> String {
let mut id = String::with_capacity(4);
for i in 0..4 {
if (code[i] as char).is_ascii_alphanumeric() {
id.push(code[i] as char);
}
}
id
}
fn do_print(code: &String) -> bool {
if *code != String::from("BR")
&& *code != String::from("DATA")
&& *code != String::from("DNA1")
&& *code != String::from("GLOB")
&& *code != String::from("GR")
&& *code != String::from("LS")
&& *code != String::from("PL")
&& *code != String::from("REND")
&& *code != String::from("SC")
&& *code != String::from("SN")
&& *code != String::from("TEST")
&& *code != String::from("WM")
&& *code != String::from("WS")
{
true
} else {
false
}
}
fn read_names(
print_dna: bool,
f: &mut File,
nr_names: usize,
names: &mut Vec<String>,
byte_counter: &mut usize,
) -> std::io::Result<()> {
let mut name_counter: usize = 0;
let mut buffer = [0; 1];
loop {
if names.len() == nr_names {
break;
} else {
let mut name = String::new();
loop {
f.read(&mut buffer)?;
*byte_counter += 1;
if buffer[0] == 0 {
break;
} else {
name.push(buffer[0] as char);
}
}
names.push(name);
name_counter += 1;
}
}
if print_dna {
println!(" {} names found in {} bytes", name_counter, byte_counter);
}
Ok(())
}
fn read_type_names(
print_dna: bool,
f: &mut File,
nr_types: usize,
type_names: &mut Vec<String>,
byte_counter: &mut usize,
) -> std::io::Result<()> {
let mut name_counter: usize = 0;
let mut buffer = [0; 1];
loop {
if type_names.len() == nr_types {
break;
} else {
let mut name = String::new();
loop {
f.read(&mut buffer)?;
*byte_counter += 1;
if buffer[0] == 0 {
break;
} else {
name.push(buffer[0] as char);
}
}
type_names.push(name);
name_counter += 1;
}
}
if print_dna {
println!(
" {} type names found in {} bytes",
name_counter, byte_counter
);
}
Ok(())
}
pub fn calc_mem_tlen(member: &DnaStrMember, type_found: u16) -> u16 {
let mut mem_tlen: u16 = 0;
let mut chars = member.mem_name.chars();
if let Some(c) = chars.next() {
if c == '*' {
if let Some(cl) = chars.last() {
if cl == ']' {
let mut chars2 = member.mem_name.chars();
let radix: u32 = 10;
let mut number_index: usize = 0;
let mut numbers: Vec<u32> = Vec::with_capacity(2 as usize);
let mut start: bool = false;
while let Some(c2) = chars2.next() {
if !start && c2 == '[' {
numbers.push(0);
start = true;
} else if start && c2 == '[' {
number_index += 1;
numbers.push(0);
} else if start && c2.is_digit(radix) {
numbers[number_index] *= radix;
numbers[number_index] += c2.to_digit(radix).unwrap();
}
}
if numbers.len() == 1 {
mem_tlen = (numbers[0] as u16) * mem::size_of::<usize>() as u16;
} else if numbers.len() == 3 {
mem_tlen = (numbers[0] as u16)
* (numbers[1] as u16)
* (numbers[2] as u16)
* mem::size_of::<usize>() as u16;
} else {
mem_tlen = (numbers[0] as u16)
* (numbers[1] as u16)
* mem::size_of::<usize>() as u16;
}
} else {
mem_tlen = mem::size_of::<usize>() as u16;
}
}
} else if c == '(' {
if let Some(c2) = chars.next() {
if c2 == '*' {
mem_tlen = mem::size_of::<usize>() as u16;
} else {
println!("TODO: {:?}", chars);
}
} else {
println!("TODO: {:?}", chars);
}
} else {
if let Some(cl) = chars.last() {
if cl == ']' {
let mut chars2 = member.mem_name.chars();
let radix: u32 = 10;
let mut number_index: usize = 0;
let mut numbers: Vec<u32> = Vec::with_capacity(2 as usize);
let mut start: bool = false;
while let Some(c2) = chars2.next() {
if !start && c2 == '[' {
numbers.push(0);
start = true;
} else if start && c2 == '[' {
number_index += 1;
numbers.push(0);
} else if start && c2.is_digit(radix) {
numbers[number_index] *= radix;
numbers[number_index] += c2.to_digit(radix).unwrap();
}
}
if numbers.len() == 1 {
mem_tlen = (numbers[0] as u16) * type_found;
} else {
mem_tlen = (numbers[0] as u16) * (numbers[1] as u16) * type_found;
}
} else {
mem_tlen = type_found;
}
} else {
mem_tlen = type_found;
}
}
}
mem_tlen
}
pub fn get_id_name(
member: &DnaStrMember,
bytes_read: &[u8],
byte_index: usize,
dna_structs_hm: &HashMap<String, DnaStrC>,
dna_types_hm: &HashMap<String, u16>,
) -> String {
let mut return_str: String = String::new();
if let Some(struct_found2) = dna_structs_hm.get(member.mem_type.as_str()) {
let mut byte_index2: usize = 0;
for member2 in &struct_found2.members {
if let Some(type_found2) = dna_types_hm.get(&member2.mem_type) {
let mem_tlen2: u16 = calc_mem_tlen(member2, *type_found2);
if member2.mem_name.contains("name") {
let mut id = String::with_capacity(mem_tlen2 as usize);
for i in 0..mem_tlen2 as usize {
if bytes_read[byte_index + byte_index2 + i] == 0 {
break;
}
id.push(bytes_read[byte_index + byte_index2 + i] as char);
}
return_str = id;
byte_index2 += mem_tlen2 as usize;
} else {
byte_index2 += mem_tlen2 as usize;
}
}
}
}
return_str
}
pub fn get_char(member: &DnaStrMember, bytes_read: &[u8], byte_index: usize) -> u8 {
let mut char_value: u8 = 0;
if member.mem_type.as_str() == "char" {
char_value = bytes_read[byte_index];
}
char_value
}
pub fn get_float(member: &DnaStrMember, bytes_read: &[u8], byte_index: usize) -> f32 {
let mut float_value: f32 = 0.0;
if member.mem_type.as_str() == "float" {
let mut float_buf: [u8; 4] = [0_u8; 4];
for i in 0..4 as usize {
float_buf[i] = bytes_read[byte_index + i];
}
float_value = unsafe { mem::transmute(float_buf) };
} else {
println!("WARNING: \"float\" expected, {:?} found", member.mem_type);
}
float_value
}
pub fn get_float2(member: &DnaStrMember, bytes_read: &[u8], byte_index: usize) -> [f32; 2] {
let mut float_values: [f32; 2] = [0.0; 2];
if member.mem_type.as_str() == "float" {
for i in 0..2 {
let mut float_buf: [u8; 4] = [0_u8; 4];
for b in 0..4 as usize {
float_buf[b] = bytes_read[byte_index + i * 4 + b];
}
float_values[i] = unsafe { mem::transmute(float_buf) };
}
} else {
println!("WARNING: \"float\" expected, {:?} found", member.mem_type);
}
float_values
}
pub fn get_float3(member: &DnaStrMember, bytes_read: &[u8], byte_index: usize) -> [f32; 3] {
let mut float_values: [f32; 3] = [0.0; 3];
if member.mem_type.as_str() == "float" {
for i in 0..3 {
let mut float_buf: [u8; 4] = [0_u8; 4];
for b in 0..4 as usize {
float_buf[b] = bytes_read[byte_index + i * 4 + b];
}
float_values[i] = unsafe { mem::transmute(float_buf) };
}
} else {
println!("WARNING: \"float\" expected, {:?} found", member.mem_type);
}
float_values
}
pub fn get_float4(member: &DnaStrMember, bytes_read: &[u8], byte_index: usize) -> [f32; 4] {
let mut float_values: [f32; 4] = [0.0; 4];
if member.mem_type.as_str() == "float" {
for i in 0..4 {
let mut float_buf: [u8; 4] = [0_u8; 4];
for b in 0..4 as usize {
float_buf[b] = bytes_read[byte_index + i * 4 + b];
}
float_values[i] = unsafe { mem::transmute(float_buf) };
}
} else {
println!("WARNING: \"float\" expected, {:?} found", member.mem_type);
}
float_values
}
pub fn get_int(member: &DnaStrMember, bytes_read: &[u8], byte_index: usize) -> i32 {
let mut int_value: i32 = 0;
if member.mem_type.as_str() == "int" {
int_value += (bytes_read[byte_index] as i32) << 0;
int_value += (bytes_read[byte_index + 1] as i32) << 8;
int_value += (bytes_read[byte_index + 2] as i32) << 16;
int_value += (bytes_read[byte_index + 3] as i32) << 24;
} else {
println!("WARNING: \"int\" expected, {:?} found", member.mem_type);
}
int_value
}
pub fn get_matrix(member: &DnaStrMember, bytes_read: &[u8], byte_index: usize) -> [f32; 16] {
let mut mat_values: [f32; 16] = [0.0_f32; 16];
if member.mem_type.as_str() == "float" {
let mut skip_bytes: usize = 0;
for i in 0..4 {
for j in 0..4 {
let mut mat_buf: [u8; 4] = [0_u8; 4];
for b in 0..4 as usize {
mat_buf[b] = bytes_read[byte_index + skip_bytes + b];
}
let mat: f32 = unsafe { mem::transmute(mat_buf) };
mat_values[i * 4 + j] = mat;
skip_bytes += 4;
}
}
} else {
println!("WARNING: \"float\" expected, {:?} found", member.mem_type);
}
mat_values
}
pub fn get_pointer(_member: &DnaStrMember, bytes_read: &[u8], byte_index: usize) -> usize {
let mut pointer_value: usize = 0;
pointer_value += (bytes_read[byte_index] as usize) << 0;
pointer_value += (bytes_read[byte_index + 1] as usize) << 8;
pointer_value += (bytes_read[byte_index + 2] as usize) << 16;
pointer_value += (bytes_read[byte_index + 3] as usize) << 24;
pointer_value += (bytes_read[byte_index + 4] as usize) << 32;
pointer_value += (bytes_read[byte_index + 5] as usize) << 40;
pointer_value += (bytes_read[byte_index + 6] as usize) << 48;
pointer_value += (bytes_read[byte_index + 7] as usize) << 56;
pointer_value
}
pub fn get_short(member: &DnaStrMember, bytes_read: &[u8], byte_index: usize) -> i16 {
let mut short_value: i16 = 0;
if member.mem_type.as_str() == "short" {
short_value += (bytes_read[byte_index] as i16) << 0;
short_value += (bytes_read[byte_index + 1] as i16) << 8;
} else {
println!("WARNING: \"short\" expected, {:?} found", member.mem_type);
}
short_value
}
pub fn get_short3(member: &DnaStrMember, bytes_read: &[u8], byte_index: usize) -> [i16; 3] {
let mut short_values: [i16; 3] = [0; 3];
if member.mem_type.as_str() == "short" {
for i in 0..3 {
let mut short_value: i16 = 0;
short_value += (bytes_read[byte_index] as i16) << 0;
short_value += (bytes_read[byte_index + 1] as i16) << 8;
short_values[i] = short_value;
}
} else {
println!("WARNING: \"short\" expected, {:?} found", member.mem_type);
}
short_values
}
pub fn print_pointer(
pointer: usize,
struct_name: &String,
dna_pointers_hm: &HashMap<usize, usize>,
) {
if pointer != 0_usize {
if let Some(pointer_found) = dna_pointers_hm.get(&pointer) {
println!(
"{} = {:#010x} ({:#018x})",
struct_name, pointer_found, pointer
);
}
} else {
println!("{} = NULL", struct_name);
}
}
pub fn read_dna(
print_dna: bool,
print_pointers: bool,
path: &std::path::PathBuf,
dna_types_hm: &mut HashMap<String, u16>,
dna_structs_hm: &mut HashMap<String, DnaStrC>,
dna_pointers_hm: &mut HashMap<usize, usize>,
dna_2_type_id: &mut Vec<u16>,
types: &mut Vec<String>,
bytes_read: &mut usize,
) -> std::io::Result<()> {
let mut f = File::open(path)?;
let mut counter: usize = 0;
let mut chunk_start: usize;
let mut buffer = [0; 12];
f.read(&mut buffer)?;
counter += 12;
let mut blender_version: u32 = 0;
if !decode_blender_header(print_dna, &buffer, &mut blender_version) {
println!("ERROR: Not a .blend file");
println!("First 12 bytes:");
println!("{:?}", buffer);
} else {
let mut current_code: String = String::new();
let mut data_counter: u32 = 0;
loop {
chunk_start = counter;
let mut buffer = [0; 4];
f.read(&mut buffer)?;
counter += 4;
let code = make_id(&buffer);
let mut buffer = [0; 4];
f.read(&mut buffer)?;
counter += 4;
let mut len: u32 = 0;
len += (buffer[0] as u32) << 0;
len += (buffer[1] as u32) << 8;
len += (buffer[2] as u32) << 16;
len += (buffer[3] as u32) << 24;
if code != String::from("DATA") {
if current_code != String::from("")
{
if do_print(¤t_code) {
if print_dna {
println!(" {} has {} data blocks", current_code, data_counter);
}
}
}
current_code = code.clone();
} else {
data_counter += 1;
}
if do_print(&code) {
if print_dna {
println!("{} ({})", code, len);
}
}
if code != String::from("DATA") {
data_counter = 0;
}
let mut buffer = [0; 8];
f.read(&mut buffer)?;
counter += 8;
let mut old: usize = 0;
old += (buffer[0] as usize) << 0;
old += (buffer[1] as usize) << 8;
old += (buffer[2] as usize) << 16;
old += (buffer[3] as usize) << 24;
old += (buffer[4] as usize) << 32;
old += (buffer[5] as usize) << 40;
old += (buffer[6] as usize) << 48;
old += (buffer[7] as usize) << 56;
if print_pointers {
println!("{:?} = {:#018x}", code, old);
}
dna_pointers_hm.insert(old, chunk_start);
let mut buffer = [0; 4];
f.read(&mut buffer)?;
counter += 4;
let mut sdna_nr: u32 = 0;
sdna_nr += (buffer[0] as u32) << 0;
sdna_nr += (buffer[1] as u32) << 8;
sdna_nr += (buffer[2] as u32) << 16;
sdna_nr += (buffer[3] as u32) << 24;
if do_print(&code) {
if print_dna {
println!("SDNAnr = {} ({})", sdna_nr, len);
}
}
let mut buffer = [0; 4];
f.read(&mut buffer)?;
counter += 4;
if code != String::from("DATA") {
}
if code == String::from("ENDB") {
break;
}
if code == String::from("DNA1") {
if print_dna {
println!("{} ({})", code, len);
}
let mut buffer = [0; 8];
f.read(&mut buffer)?;
counter += 8;
let mut sdna_name = String::with_capacity(8);
for i in 0..8 {
if (buffer[i] as char).is_ascii_alphabetic() {
sdna_name.push(buffer[i] as char);
}
}
if sdna_name != String::from("SDNANAME") {
println!("WARNING: \"SDNANAME\" expected, {:?} found", sdna_name);
let mut buffer = vec![0; (len - 8) as usize];
f.read(&mut buffer)?;
counter += (len - 8) as usize;
} else {
if print_dna {
println!(" {}", sdna_name);
}
let mut buffer = [0; 4];
f.read(&mut buffer)?;
counter += 4;
let mut nr_names: u32 = 0;
nr_names += (buffer[0] as u32) << 0;
nr_names += (buffer[1] as u32) << 8;
nr_names += (buffer[2] as u32) << 16;
nr_names += (buffer[3] as u32) << 24;
if print_dna {
println!(" expect {} names", nr_names);
}
let mut names: Vec<String> = Vec::with_capacity(nr_names as usize);
let mut names_len: usize = 0;
read_names(
print_dna,
&mut f,
nr_names as usize,
&mut names,
&mut names_len,
)?;
counter += names_len;
let mut remaining_bytes: usize = (len - 12) as usize - names_len;
let mut buffer = [0; 1];
loop {
f.read(&mut buffer)?;
counter += 1;
if buffer[0] == 0 {
remaining_bytes -= 1;
} else if buffer[0] as char == 'T' {
remaining_bytes -= 1;
break;
}
}
let mut buffer = [0; 3];
f.read(&mut buffer)?;
counter += 3;
remaining_bytes -= 3;
if buffer[0] as char == 'Y'
&& buffer[1] as char == 'P'
&& buffer[2] as char == 'E'
{
let mut buffer = [0; 4];
f.read(&mut buffer)?;
counter += 4;
remaining_bytes -= 4;
let mut nr_types: u32 = 0;
nr_types += (buffer[0] as u32) << 0;
nr_types += (buffer[1] as u32) << 8;
nr_types += (buffer[2] as u32) << 16;
nr_types += (buffer[3] as u32) << 24;
if print_dna {
println!(" expect {} type names", nr_types);
}
let mut types_len: usize = 0;
read_type_names(
print_dna,
&mut f,
nr_types as usize,
types,
&mut types_len,
)?;
counter += types_len;
remaining_bytes -= types_len;
let mut tlen: Vec<u16> = Vec::new();
let mut buffer = [0; 1];
loop {
f.read(&mut buffer)?;
counter += 1;
if buffer[0] == 0 {
remaining_bytes -= 1;
} else if buffer[0] as char == 'T' {
remaining_bytes -= 1;
break;
}
}
let mut buffer = [0; 3];
f.read(&mut buffer)?;
counter += 3;
remaining_bytes -= 3;
if buffer[0] as char == 'L'
&& buffer[1] as char == 'E'
&& buffer[2] as char == 'N'
{
for i in 0..nr_types as usize {
let mut buffer = [0; 2];
f.read(&mut buffer)?;
counter += 2;
remaining_bytes -= 2;
let mut type_size: u16 = 0;
type_size += (buffer[0] as u16) << 0;
type_size += (buffer[1] as u16) << 8;
tlen.push(type_size);
dna_types_hm.insert(types[i].clone(), type_size);
}
let mut buffer = [0; 1];
loop {
f.read(&mut buffer)?;
counter += 1;
if buffer[0] == 0 {
remaining_bytes -= 1;
} else if buffer[0] as char == 'S' {
remaining_bytes -= 1;
break;
}
}
let mut buffer = [0; 3];
f.read(&mut buffer)?;
counter += 3;
remaining_bytes -= 3;
if buffer[0] as char == 'T'
&& buffer[1] as char == 'R'
&& buffer[2] as char == 'C'
{
let mut buffer = [0; 4];
f.read(&mut buffer)?;
counter += 4;
remaining_bytes -= 4;
let mut nr_structs: u32 = 0;
nr_structs += (buffer[0] as u32) << 0;
nr_structs += (buffer[1] as u32) << 8;
nr_structs += (buffer[2] as u32) << 16;
nr_structs += (buffer[3] as u32) << 24;
if print_dna {
println!(" expect {} struct pointers", nr_structs);
}
for s in 0..nr_structs as usize {
let mut buffer = [0; 2];
f.read(&mut buffer)?;
counter += 2;
remaining_bytes -= 2;
let mut type_idx: u16 = 0;
type_idx += (buffer[0] as u16) << 0;
type_idx += (buffer[1] as u16) << 8;
f.read(&mut buffer)?;
counter += 2;
remaining_bytes -= 2;
let mut short2: u16 = 0;
short2 += (buffer[0] as u16) << 0;
short2 += (buffer[1] as u16) << 8;
dna_2_type_id.push(type_idx);
if print_dna {
println!(" [SDNAnr = {}]", s);
println!(
" {} (len={}) {{",
types[type_idx as usize], tlen[type_idx as usize]
);
}
let tuple_counter: usize = short2 as usize;
let mut members: Vec<DnaStrMember> =
Vec::with_capacity(tuple_counter as usize);
for _t in 0..tuple_counter {
let mut buffer = [0; 2];
f.read(&mut buffer)?;
counter += 2;
remaining_bytes -= 2;
let mut type_idx: u16 = 0;
type_idx += (buffer[0] as u16) << 0;
type_idx += (buffer[1] as u16) << 8;
f.read(&mut buffer)?;
counter += 2;
remaining_bytes -= 2;
let mut name_idx: u16 = 0;
name_idx += (buffer[0] as u16) << 0;
name_idx += (buffer[1] as u16) << 8;
if print_dna {
println!(
" {} {};",
types[type_idx as usize], names[name_idx as usize]
);
}
let member = DnaStrMember::new(
types[type_idx as usize].clone(),
names[name_idx as usize].clone(),
);
members.push(member);
}
if print_dna {
println!(" }}");
}
let dna_str_c = DnaStrC::new(s as u32, members);
dna_structs_hm
.insert(types[type_idx as usize].clone(), dna_str_c);
}
} else {
println!("ERROR: \"STRC\" expected, \"S\"{:?} found", buffer)
}
} else {
println!("ERROR: \"TLEN\" expected, \"T\"{:?} found", buffer)
}
} else {
println!("ERROR: \"TYPE\" expected, \"T\"{:?} found", buffer)
}
if print_dna {
println!(" remaining bytes: {}", remaining_bytes);
}
let mut buffer = vec![0; remaining_bytes];
f.read(&mut buffer)?;
counter += remaining_bytes;
}
} else {
let mut buffer = vec![0; len as usize];
f.read(&mut buffer)?;
counter += len as usize;
}
}
if print_dna {
println!("{} bytes read", counter);
}
*bytes_read = counter;
}
Ok(())
}
pub fn use_dna(
print_dna: bool,
path: &std::path::PathBuf,
dna_types_hm: &HashMap<String, u16>,
dna_structs_hm: &HashMap<String, DnaStrC>,
names: &Vec<String>,
dna_2_type_id: &Vec<u16>,
types: &Vec<String>,
bytes_read: &mut Vec<u8>,
structs_read: &mut Vec<String>,
data_read: &mut Vec<u32>,
pointers_read: &mut Vec<(usize, u32)>,
) -> std::io::Result<()> {
let mut sdna_nrs: Vec<u32> = Vec::with_capacity(names.len());
for name in names {
if let Some(struct_found) = dna_structs_hm.get(name) {
let sdna_nr: u32 = struct_found.sdna_nr;
sdna_nrs.push(sdna_nr);
}
}
let mut f = File::open(path)?;
let mut counter: usize = 0;
let mut buffer = [0; 12];
f.read(&mut buffer)?;
counter += 12;
let mut blender_version: u32 = 0;
if !decode_blender_header(print_dna, &buffer, &mut blender_version) {
println!("ERROR: Not a .blend file");
println!("First 12 bytes:");
println!("{:?}", buffer);
} else {
loop {
let mut buffer = [0; 4];
f.read(&mut buffer)?;
counter += 4;
let code = make_id(&buffer);
let mut buffer = [0; 4];
f.read(&mut buffer)?;
counter += 4;
let mut len: u32 = 0;
len += (buffer[0] as u32) << 0;
len += (buffer[1] as u32) << 8;
len += (buffer[2] as u32) << 16;
len += (buffer[3] as u32) << 24;
let mut buffer = [0; 8];
f.read(&mut buffer)?;
counter += 8;
let mut old: usize = 0;
old += (buffer[0] as usize) << 0;
old += (buffer[1] as usize) << 8;
old += (buffer[2] as usize) << 16;
old += (buffer[3] as usize) << 24;
old += (buffer[4] as usize) << 32;
old += (buffer[5] as usize) << 40;
old += (buffer[6] as usize) << 48;
old += (buffer[7] as usize) << 56;
let mut buffer = [0; 4];
f.read(&mut buffer)?;
counter += 4;
let mut sdna_nr: u32 = 0;
sdna_nr += (buffer[0] as u32) << 0;
sdna_nr += (buffer[1] as u32) << 8;
sdna_nr += (buffer[2] as u32) << 16;
sdna_nr += (buffer[3] as u32) << 24;
let mut buffer = [0; 4];
f.read(&mut buffer)?;
counter += 4;
if code == String::from("ENDB") {
break;
}
let mut buffer = vec![0; len as usize];
f.read(&mut buffer)?;
counter += len as usize;
if code == String::from("DATA") {
let type_id: usize = dna_2_type_id[sdna_nr as usize] as usize;
for search_index in 0..sdna_nrs.len() {
let name = &names[search_index];
if *name == types[type_id] {
let mut type_tlen: u16 = 0;
if let Some(tlen) = dna_types_hm.get(name) {
type_tlen = *tlen;
}
if print_dna {
println!(
"DATA ({} * {}={})",
len / type_tlen as u32,
types[type_id],
len
);
println!(
"{}[{}] (SDNAnr = {}) found in {:?}",
name, type_tlen, sdna_nr, sdna_nrs
);
}
bytes_read.append(&mut buffer);
structs_read.push(name.clone());
data_read.push(len);
pointers_read.push((old, sdna_nr));
}
}
} else {
for search_index in 0..sdna_nrs.len() {
let search_sdna_nr = sdna_nrs[search_index];
if search_sdna_nr == sdna_nr {
let name = &names[search_index];
let mut type_tlen: u16 = 0;
if let Some(tlen) = dna_types_hm.get(name) {
type_tlen = *tlen;
}
if print_dna {
println!(
"{}[{}] (SDNAnr = {}) found in {:?}",
name, type_tlen, sdna_nr, sdna_nrs
);
}
bytes_read.append(&mut buffer);
structs_read.push(name.clone());
data_read.push(len);
pointers_read.push((old, sdna_nr));
}
}
}
}
if print_dna {
println!("{} bytes read", counter);
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn get_id_name_test_01() {
let member: DnaStrMember = DnaStrMember {
mem_type: "ID".to_string(),
mem_name: "id".to_string(),
};
let bytes_read = [
8_u8, 19, 168, 78, 145, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 67, 65, 99, 117, 114, 114, 101, 110, 116, 95, 99, 97, 109, 0, 48,
48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 136, 141, 162, 78, 145, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 36, 0, 0, 0, 0, 63, 205, 204, 204, 61, 0, 0, 200, 66, 132, 205, 3, 66, 0, 0, 192,
64, 205, 204, 204, 61, 0, 0, 0, 66, 0, 0, 144, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 132, 205, 3,
66, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 30, 133, 61, 153,
153, 249, 63, 0, 0, 0, 0, 0, 0, 0, 0, 146, 10, 134, 63, 54, 141, 167, 63, 8, 20, 168,
78, 145, 127, 0, 0, 8, 18, 168, 78, 145, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 67, 65, 100, 111, 111, 114, 49, 95, 99, 97, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 200, 142, 162, 78, 145, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0,
63, 205, 204, 204, 61, 0, 0, 200, 66, 132, 205, 3, 66, 0, 0, 192, 64, 205, 204, 204,
61, 0, 0, 0, 66, 0, 0, 144, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 132, 205, 3, 66, 0, 0, 0, 66, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 30, 133, 61, 153, 153, 249, 63, 0, 0,
0, 0, 0, 0, 0, 0, 146, 10, 134, 63, 54, 141, 167, 63, 8, 21, 168, 78, 145, 127, 0, 0,
8, 19, 168, 78, 145, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 65,
100, 111, 111, 114, 50, 121, 95, 99, 97, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 8, 224, 163,
78, 145, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 63, 205, 204, 204,
61, 0, 0, 200, 66, 132, 205, 3, 66, 0, 0, 192, 64, 205, 204, 204, 61, 0, 0, 0, 66, 0,
0, 144, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 132, 205, 3, 66, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 184, 30, 133, 61, 153, 153, 249, 63, 0, 0, 0, 0, 0, 0, 0, 0,
146, 10, 134, 63, 54, 141, 167, 63, 8, 22, 168, 78, 145, 127, 0, 0, 8, 20, 168, 78,
145, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 65, 115, 104, 97,
102, 116, 95, 99, 97, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 72, 225, 163, 78, 145, 127,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 63, 205, 204, 204, 61, 0, 0, 200,
66, 150, 252, 234, 65, 0, 0, 192, 64, 205, 204, 204, 61, 0, 0, 0, 66, 0, 0, 144, 65, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 67, 150, 252, 234, 65, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 184, 30, 133, 61, 153, 153, 249, 63, 0, 0, 0, 0, 0, 0, 0, 0, 146, 10, 134,
63, 54, 141, 167, 63, 0, 0, 0, 0, 0, 0, 0, 0, 8, 21, 168, 78, 145, 127, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 65, 120, 89, 95, 99, 97, 109, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0, 0, 136, 226, 163, 78, 145, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 36, 0, 0, 0, 0, 63, 205, 204, 204, 61, 0, 0, 200, 66, 132, 205, 3, 66, 0, 0, 192,
64, 205, 204, 204, 61, 0, 0, 0, 66, 0, 0, 144, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 132, 205, 3,
66, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 30, 133, 61, 153,
153, 249, 63, 0, 0, 0, 0, 0, 0, 0, 0, 146, 10, 134, 63, 54, 141, 167, 63,
];
let dna_str_c: DnaStrC = DnaStrC {
sdna_nr: 10,
members: [
DnaStrMember {
mem_type: "void".to_string(),
mem_name: "*next".to_string(),
},
DnaStrMember {
mem_type: "void".to_string(),
mem_name: "*prev".to_string(),
},
DnaStrMember {
mem_type: "ID".to_string(),
mem_name: "*newid".to_string(),
},
DnaStrMember {
mem_type: "Library".to_string(),
mem_name: "*lib".to_string(),
},
DnaStrMember {
mem_type: "char".to_string(),
mem_name: "name[66]".to_string(),
},
DnaStrMember {
mem_type: "short".to_string(),
mem_name: "flag".to_string(),
},
DnaStrMember {
mem_type: "short".to_string(),
mem_name: "tag".to_string(),
},
DnaStrMember {
mem_type: "short".to_string(),
mem_name: "pad_s1".to_string(),
},
DnaStrMember {
mem_type: "int".to_string(),
mem_name: "us".to_string(),
},
DnaStrMember {
mem_type: "int".to_string(),
mem_name: "icon_id".to_string(),
},
DnaStrMember {
mem_type: "IDProperty".to_string(),
mem_name: "*properties".to_string(),
},
]
.to_vec(),
};
let byte_index: usize = 0;
let mut dna_structs_hm: HashMap<String, DnaStrC> = HashMap::new();
dna_structs_hm.insert("ID".to_string(), dna_str_c);
let mut dna_types_hm: HashMap<String, u16> = HashMap::new();
dna_types_hm.insert("void".to_string(), 0);
dna_types_hm.insert("Library".to_string(), 2200);
dna_types_hm.insert("char".to_string(), 1);
dna_types_hm.insert("IDPropertyData".to_string(), 32);
dna_types_hm.insert("int".to_string(), 4);
dna_types_hm.insert("ID".to_string(), 120);
dna_types_hm.insert("short".to_string(), 2);
let id: String = get_id_name(
&member,
&bytes_read,
byte_index,
&dna_structs_hm,
&dna_types_hm,
);
println!(" ID.name = {:?}", id);
let base_name = id.clone()[2..].to_string();
println!("{}", base_name);
assert_eq!(base_name, "current_cam");
}
}