Add keywords to Merchandise

This commit is contained in:
Tyler Hallada 2021-02-09 00:59:48 -05:00
parent 2052f2cac9
commit 0244914435
2 changed files with 180 additions and 62 deletions

View File

@ -98,6 +98,8 @@ struct RawMerchandise {
uint32_t form_type; uint32_t form_type;
bool is_food; bool is_food;
uint32_t price; uint32_t price;
const char **keywords;
uintptr_t keywords_len;
}; };
struct RawMerchandiseVec { struct RawMerchandiseVec {

View File

@ -32,16 +32,20 @@ pub struct Merchandise {
pub form_type: u32, pub form_type: u32,
pub is_food: bool, pub is_food: bool,
pub price: u32, pub price: u32,
pub keywords: Vec<String>,
} }
impl MerchandiseList { impl MerchandiseList {
pub fn from_game(shop_id: i32, merch_records: &[RawMerchandise]) -> Self { pub fn from_game(shop_id: i32, merch_records: &[RawMerchandise]) -> Self {
info!("MerchandiseList::from_game shop_id: {:?}", shop_id);
Self { Self {
shop_id, shop_id,
owner_id: None, owner_id: None,
form_list: merch_records form_list: merch_records
.iter() .iter()
.map(|rec| Merchandise { .map(|rec| {
info!("MerchandiseList::from_game local_form_id: {:?} keywords_len: {:?} keywords.is_null(): {:?}", rec.local_form_id, rec.keywords_len, rec.keywords.is_null());
Merchandise {
mod_name: unsafe { CStr::from_ptr(rec.mod_name) } mod_name: unsafe { CStr::from_ptr(rec.mod_name) }
.to_string_lossy() .to_string_lossy()
.to_string(), .to_string(),
@ -53,6 +57,18 @@ impl MerchandiseList {
form_type: rec.form_type, form_type: rec.form_type,
is_food: rec.is_food, is_food: rec.is_food,
price: rec.price, price: rec.price,
keywords: match rec.keywords.is_null() {
true => vec![],
false => unsafe { slice::from_raw_parts(rec.keywords, rec.keywords_len) }
.iter()
.map(|&keyword| {
unsafe { CStr::from_ptr(keyword) }
.to_string_lossy()
.to_string()
})
.collect(),
}
}
}) })
.collect(), .collect(),
} }
@ -79,6 +95,8 @@ pub struct RawMerchandise {
pub form_type: u32, pub form_type: u32,
pub is_food: bool, pub is_food: bool,
pub price: u32, pub price: u32,
pub keywords: *mut *const c_char,
pub keywords_len: usize,
} }
#[derive(Debug)] #[derive(Debug)]
@ -100,7 +118,7 @@ pub extern "C" fn create_merchandise_list(
) -> FFIResult<RawMerchandiseVec> { ) -> FFIResult<RawMerchandiseVec> {
let api_url = unsafe { CStr::from_ptr(api_url) }.to_string_lossy(); let api_url = unsafe { CStr::from_ptr(api_url) }.to_string_lossy();
let api_key = unsafe { CStr::from_ptr(api_key) }.to_string_lossy(); let api_key = unsafe { CStr::from_ptr(api_key) }.to_string_lossy();
info!("create_merchandise_list api_url: {:?}, api_key: {:?}, shop_id: {:?}, raw_merchandise_len: {:?}", api_url, api_key, shop_id, raw_merchandise_len); info!("create_merchandise_list api_url: {:?}, api_key: {:?}, shop_id: {:?}, raw_merchandise_len: {:?}, raw_merchandise_ptr: {:?}", api_url, api_key, shop_id, raw_merchandise_len, raw_merchandise_ptr);
let raw_merchandise_slice = match raw_merchandise_ptr.is_null() { let raw_merchandise_slice = match raw_merchandise_ptr.is_null() {
true => &[], true => &[],
false => unsafe { slice::from_raw_parts(raw_merchandise_ptr, raw_merchandise_len) }, false => unsafe { slice::from_raw_parts(raw_merchandise_ptr, raw_merchandise_len) },
@ -157,7 +175,16 @@ pub extern "C" fn create_merchandise_list(
let (ptr, len, cap) = merchandise_list let (ptr, len, cap) = merchandise_list
.form_list .form_list
.into_iter() .into_iter()
.map(|merchandise| RawMerchandise { .map(|merchandise| {
let (keywords_ptr, keywords_len, _) = merchandise
.keywords
.into_iter()
.map(|keyword| {
CString::new(keyword).unwrap_or_default().into_raw() as *const c_char
})
.collect::<Vec<*const c_char>>()
.into_raw_parts();
RawMerchandise {
mod_name: CString::new(merchandise.mod_name) mod_name: CString::new(merchandise.mod_name)
.unwrap_or_default() .unwrap_or_default()
.into_raw(), .into_raw(),
@ -169,6 +196,9 @@ pub extern "C" fn create_merchandise_list(
form_type: merchandise.form_type, form_type: merchandise.form_type,
is_food: merchandise.is_food, is_food: merchandise.is_food,
price: merchandise.price, price: merchandise.price,
keywords: keywords_ptr,
keywords_len: keywords_len,
}
}) })
.collect::<Vec<RawMerchandise>>() .collect::<Vec<RawMerchandise>>()
.into_raw_parts(); .into_raw_parts();
@ -197,7 +227,7 @@ pub extern "C" fn update_merchandise_list(
) -> FFIResult<RawMerchandiseVec> { ) -> FFIResult<RawMerchandiseVec> {
let api_url = unsafe { CStr::from_ptr(api_url) }.to_string_lossy(); let api_url = unsafe { CStr::from_ptr(api_url) }.to_string_lossy();
let api_key = unsafe { CStr::from_ptr(api_key) }.to_string_lossy(); let api_key = unsafe { CStr::from_ptr(api_key) }.to_string_lossy();
info!("create_merchandise_list api_url: {:?}, api_key: {:?}, shop_id: {:?}, raw_merchandise_len: {:?}", api_url, api_key, shop_id, raw_merchandise_len); info!("update_merchandise_list api_url: {:?}, api_key: {:?}, shop_id: {:?}, raw_merchandise_len: {:?}, raw_merchandise_ptr: {:?}", api_url, api_key, shop_id, raw_merchandise_len, raw_merchandise_ptr);
let raw_merchandise_slice = match raw_merchandise_ptr.is_null() { let raw_merchandise_slice = match raw_merchandise_ptr.is_null() {
true => &[], true => &[],
false => unsafe { slice::from_raw_parts(raw_merchandise_ptr, raw_merchandise_len) }, false => unsafe { slice::from_raw_parts(raw_merchandise_ptr, raw_merchandise_len) },
@ -250,7 +280,16 @@ pub extern "C" fn update_merchandise_list(
let (ptr, len, cap) = merchandise_list let (ptr, len, cap) = merchandise_list
.form_list .form_list
.into_iter() .into_iter()
.map(|merchandise| RawMerchandise { .map(|merchandise| {
let (keywords_ptr, keywords_len, _) = merchandise
.keywords
.into_iter()
.map(|keyword| {
CString::new(keyword).unwrap_or_default().into_raw() as *const c_char
})
.collect::<Vec<*const c_char>>()
.into_raw_parts();
RawMerchandise {
mod_name: CString::new(merchandise.mod_name) mod_name: CString::new(merchandise.mod_name)
.unwrap_or_default() .unwrap_or_default()
.into_raw(), .into_raw(),
@ -262,6 +301,9 @@ pub extern "C" fn update_merchandise_list(
form_type: merchandise.form_type, form_type: merchandise.form_type,
is_food: merchandise.is_food, is_food: merchandise.is_food,
price: merchandise.price, price: merchandise.price,
keywords: keywords_ptr,
keywords_len: keywords_len,
}
}) })
.collect::<Vec<RawMerchandise>>() .collect::<Vec<RawMerchandise>>()
.into_raw_parts(); .into_raw_parts();
@ -355,7 +397,16 @@ pub extern "C" fn get_merchandise_list(
let (ptr, len, cap) = merchandise_list let (ptr, len, cap) = merchandise_list
.form_list .form_list
.into_iter() .into_iter()
.map(|merchandise| RawMerchandise { .map(|merchandise| {
let (keywords_ptr, keywords_len, _) = merchandise
.keywords
.into_iter()
.map(|keyword| {
CString::new(keyword).unwrap_or_default().into_raw() as *const c_char
})
.collect::<Vec<*const c_char>>()
.into_raw_parts();
RawMerchandise {
mod_name: CString::new(merchandise.mod_name) mod_name: CString::new(merchandise.mod_name)
.unwrap_or_default() .unwrap_or_default()
.into_raw(), .into_raw(),
@ -367,6 +418,9 @@ pub extern "C" fn get_merchandise_list(
form_type: merchandise.form_type, form_type: merchandise.form_type,
is_food: merchandise.is_food, is_food: merchandise.is_food,
price: merchandise.price, price: merchandise.price,
keywords: keywords_ptr,
keywords_len: keywords_len,
}
}) })
.collect::<Vec<RawMerchandise>>() .collect::<Vec<RawMerchandise>>()
.into_raw_parts(); .into_raw_parts();
@ -453,7 +507,16 @@ pub extern "C" fn get_merchandise_list_by_shop_id(
let (ptr, len, cap) = merchandise_list let (ptr, len, cap) = merchandise_list
.form_list .form_list
.into_iter() .into_iter()
.map(|merchandise| RawMerchandise { .map(|merchandise| {
let (keywords_ptr, keywords_len, _) = merchandise
.keywords
.into_iter()
.map(|keyword| {
CString::new(keyword).unwrap_or_default().into_raw() as *const c_char
})
.collect::<Vec<*const c_char>>()
.into_raw_parts();
RawMerchandise {
mod_name: CString::new(merchandise.mod_name) mod_name: CString::new(merchandise.mod_name)
.unwrap_or_default() .unwrap_or_default()
.into_raw(), .into_raw(),
@ -465,6 +528,9 @@ pub extern "C" fn get_merchandise_list_by_shop_id(
form_type: merchandise.form_type, form_type: merchandise.form_type,
is_food: merchandise.is_food, is_food: merchandise.is_food,
price: merchandise.price, price: merchandise.price,
keywords: keywords_ptr,
keywords_len: keywords_len,
}
}) })
.collect::<Vec<RawMerchandise>>() .collect::<Vec<RawMerchandise>>()
.into_raw_parts(); .into_raw_parts();
@ -505,6 +571,7 @@ mod tests {
form_type: 1, form_type: 1,
is_food: false, is_food: false,
price: 100, price: 100,
keywords: vec!["VendorItemWeapon".to_string()],
}], }],
created_at: Utc::now().naive_utc(), created_at: Utc::now().naive_utc(),
updated_at: Utc::now().naive_utc(), updated_at: Utc::now().naive_utc(),
@ -515,6 +582,9 @@ mod tests {
.with_body(bincode::serialize(&example).unwrap()) .with_body(bincode::serialize(&example).unwrap())
.create(); .create();
let (keywords, keywords_len, _) =
vec![CString::new("VendorItemWeapon").unwrap().into_raw() as *const c_char]
.into_raw_parts();
let api_url = CString::new("url").unwrap().into_raw(); let api_url = CString::new("url").unwrap().into_raw();
let api_key = CString::new("api-key").unwrap().into_raw(); let api_key = CString::new("api-key").unwrap().into_raw();
let (ptr, len, _cap) = vec![RawMerchandise { let (ptr, len, _cap) = vec![RawMerchandise {
@ -525,6 +595,8 @@ mod tests {
form_type: 1, form_type: 1,
is_food: false, is_food: false,
price: 100, price: 100,
keywords,
keywords_len,
}] }]
.into_raw_parts(); .into_raw_parts();
let result = create_merchandise_list(api_url, api_key, 1, ptr, len); let result = create_merchandise_list(api_url, api_key, 1, ptr, len);
@ -570,6 +642,9 @@ mod tests {
.with_body("Internal Server Error") .with_body("Internal Server Error")
.create(); .create();
let (keywords, keywords_len, _) =
vec![CString::new("VendorItemWeapon").unwrap().into_raw() as *const c_char]
.into_raw_parts();
let api_url = CString::new("url").unwrap().into_raw(); let api_url = CString::new("url").unwrap().into_raw();
let api_key = CString::new("api-key").unwrap().into_raw(); let api_key = CString::new("api-key").unwrap().into_raw();
let (ptr, len, _cap) = vec![RawMerchandise { let (ptr, len, _cap) = vec![RawMerchandise {
@ -580,6 +655,8 @@ mod tests {
form_type: 1, form_type: 1,
is_food: false, is_food: false,
price: 100, price: 100,
keywords,
keywords_len,
}] }]
.into_raw_parts(); .into_raw_parts();
let result = create_merchandise_list(api_url, api_key, 1, ptr, len); let result = create_merchandise_list(api_url, api_key, 1, ptr, len);
@ -612,6 +689,7 @@ mod tests {
form_type: 1, form_type: 1,
is_food: false, is_food: false,
price: 100, price: 100,
keywords: vec!["VendorItemWeapon".to_string()],
}], }],
created_at: Utc::now().naive_utc(), created_at: Utc::now().naive_utc(),
updated_at: Utc::now().naive_utc(), updated_at: Utc::now().naive_utc(),
@ -622,6 +700,9 @@ mod tests {
.with_body(bincode::serialize(&example).unwrap()) .with_body(bincode::serialize(&example).unwrap())
.create(); .create();
let (keywords, keywords_len, _) =
vec![CString::new("VendorItemWeapon").unwrap().into_raw() as *const c_char]
.into_raw_parts();
let api_url = CString::new("url").unwrap().into_raw(); let api_url = CString::new("url").unwrap().into_raw();
let api_key = CString::new("api-key").unwrap().into_raw(); let api_key = CString::new("api-key").unwrap().into_raw();
let (ptr, len, _cap) = vec![RawMerchandise { let (ptr, len, _cap) = vec![RawMerchandise {
@ -632,6 +713,8 @@ mod tests {
form_type: 1, form_type: 1,
is_food: false, is_food: false,
price: 100, price: 100,
keywords,
keywords_len,
}] }]
.into_raw_parts(); .into_raw_parts();
let result = update_merchandise_list(api_url, api_key, 1, ptr, len); let result = update_merchandise_list(api_url, api_key, 1, ptr, len);
@ -677,6 +760,9 @@ mod tests {
.with_body("Internal Server Error") .with_body("Internal Server Error")
.create(); .create();
let (keywords, keywords_len, _) =
vec![CString::new("VendorItemWeapon").unwrap().into_raw() as *const c_char]
.into_raw_parts();
let api_url = CString::new("url").unwrap().into_raw(); let api_url = CString::new("url").unwrap().into_raw();
let api_key = CString::new("api-key").unwrap().into_raw(); let api_key = CString::new("api-key").unwrap().into_raw();
let (ptr, len, _cap) = vec![RawMerchandise { let (ptr, len, _cap) = vec![RawMerchandise {
@ -687,6 +773,8 @@ mod tests {
form_type: 1, form_type: 1,
is_food: false, is_food: false,
price: 100, price: 100,
keywords,
keywords_len,
}] }]
.into_raw_parts(); .into_raw_parts();
let result = update_merchandise_list(api_url, api_key, 1, ptr, len); let result = update_merchandise_list(api_url, api_key, 1, ptr, len);
@ -718,6 +806,7 @@ mod tests {
form_type: 1, form_type: 1,
is_food: false, is_food: false,
price: 100, price: 100,
keywords: vec!["VendorItemWeapon".to_string()],
}], }],
created_at: Utc::now().naive_utc(), created_at: Utc::now().naive_utc(),
updated_at: Utc::now().naive_utc(), updated_at: Utc::now().naive_utc(),
@ -728,6 +817,9 @@ mod tests {
.with_body(bincode::serialize(&example).unwrap()) .with_body(bincode::serialize(&example).unwrap())
.create(); .create();
let (keywords, keywords_len, _) =
vec![CString::new("VendorItemWeapon").unwrap().into_raw() as *const c_char]
.into_raw_parts();
let api_url = CString::new("url").unwrap().into_raw(); let api_url = CString::new("url").unwrap().into_raw();
let api_key = CString::new("api-key").unwrap().into_raw(); let api_key = CString::new("api-key").unwrap().into_raw();
let result = get_merchandise_list(api_url, api_key, 1); let result = get_merchandise_list(api_url, api_key, 1);
@ -757,6 +849,16 @@ mod tests {
assert_eq!(raw_merchandise.form_type, 1); assert_eq!(raw_merchandise.form_type, 1);
assert_eq!(raw_merchandise.is_food, false); assert_eq!(raw_merchandise.is_food, false);
assert_eq!(raw_merchandise.price, 100); assert_eq!(raw_merchandise.price, 100);
assert!(!raw_merchandise.keywords.is_null());
let keywords_slice = unsafe {
slice::from_raw_parts(raw_merchandise.keywords, raw_merchandise.keywords_len)
};
assert_eq!(
unsafe { CStr::from_ptr(keywords_slice[0]) }
.to_string_lossy()
.to_string(),
"VendorItemWeapon".to_string(),
);
} }
FFIResult::Err(error) => panic!("get_merchandise_list returned error: {:?}", unsafe { FFIResult::Err(error) => panic!("get_merchandise_list returned error: {:?}", unsafe {
CStr::from_ptr(error).to_string_lossy() CStr::from_ptr(error).to_string_lossy()
@ -803,6 +905,7 @@ mod tests {
form_type: 1, form_type: 1,
is_food: false, is_food: false,
price: 100, price: 100,
keywords: vec!["VendorItemWeapon".to_string()],
}], }],
created_at: Utc::now().naive_utc(), created_at: Utc::now().naive_utc(),
updated_at: Utc::now().naive_utc(), updated_at: Utc::now().naive_utc(),
@ -813,6 +916,9 @@ mod tests {
.with_body(bincode::serialize(&example).unwrap()) .with_body(bincode::serialize(&example).unwrap())
.create(); .create();
let (keywords, keywords_len, _) =
vec![CString::new("VendorItemWeapon").unwrap().into_raw() as *const c_char]
.into_raw_parts();
let api_url = CString::new("url").unwrap().into_raw(); let api_url = CString::new("url").unwrap().into_raw();
let api_key = CString::new("api-key").unwrap().into_raw(); let api_key = CString::new("api-key").unwrap().into_raw();
let result = get_merchandise_list_by_shop_id(api_url, api_key, 1); let result = get_merchandise_list_by_shop_id(api_url, api_key, 1);
@ -842,6 +948,16 @@ mod tests {
assert_eq!(raw_merchandise.form_type, 1); assert_eq!(raw_merchandise.form_type, 1);
assert_eq!(raw_merchandise.is_food, false); assert_eq!(raw_merchandise.is_food, false);
assert_eq!(raw_merchandise.price, 100); assert_eq!(raw_merchandise.price, 100);
assert!(!raw_merchandise.keywords.is_null());
let keywords_slice = unsafe {
slice::from_raw_parts(raw_merchandise.keywords, raw_merchandise.keywords_len)
};
assert_eq!(
unsafe { CStr::from_ptr(keywords_slice[0]) }
.to_string_lossy()
.to_string(),
"VendorItemWeapon".to_string(),
);
} }
FFIResult::Err(error) => panic!( FFIResult::Err(error) => panic!(
"get_merchandise_list_by_shop_id returned error: {:?}", "get_merchandise_list_by_shop_id returned error: {:?}",