Add get and update shop methods
This commit is contained in:
parent
ae20df0a69
commit
0aa3e64dc8
44
bindings.h
44
bindings.h
@ -29,10 +29,10 @@ struct MerchRecord {
|
|||||||
uint32_t price;
|
uint32_t price;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RefRecordVec {
|
struct ShopRecord {
|
||||||
RefRecord *ptr;
|
int32_t id;
|
||||||
uintptr_t len;
|
const char *name;
|
||||||
uintptr_t cap;
|
const char *description;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -89,6 +89,12 @@ struct FFIResult {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct RefRecordVec {
|
||||||
|
RefRecord *ptr;
|
||||||
|
uintptr_t len;
|
||||||
|
uintptr_t cap;
|
||||||
|
};
|
||||||
|
|
||||||
struct MerchRecordVec {
|
struct MerchRecordVec {
|
||||||
MerchRecord *ptr;
|
MerchRecord *ptr;
|
||||||
uintptr_t len;
|
uintptr_t len;
|
||||||
@ -97,11 +103,9 @@ struct MerchRecordVec {
|
|||||||
|
|
||||||
/* bad hack added by thallada. See: https://github.com/eqrion/cbindgen/issues/402 */
|
/* bad hack added by thallada. See: https://github.com/eqrion/cbindgen/issues/402 */
|
||||||
struct _Helper_0 {
|
struct _Helper_0 {
|
||||||
FFIResult<RefRecordVec> field;
|
FFIResult<RefRecordVec> ref_record_vec_result;
|
||||||
};
|
FFIResult<MerchRecordVec> merch_record_vec_result;
|
||||||
|
FFIResult<ShopRecord> shop_record_result;
|
||||||
struct _Helper_1 {
|
|
||||||
FFIResult<MerchRecordVec> field;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// dummy extern C block to close curly brace
|
// dummy extern C block to close curly brace
|
||||||
@ -128,10 +132,10 @@ int32_t create_owner(const char *api_url,
|
|||||||
const char *name,
|
const char *name,
|
||||||
uint32_t mod_version);
|
uint32_t mod_version);
|
||||||
|
|
||||||
int32_t create_shop(const char *api_url,
|
FFIResult<ShopRecord> create_shop(const char *api_url,
|
||||||
const char *api_key,
|
const char *api_key,
|
||||||
const char *name,
|
const char *name,
|
||||||
const char *description);
|
const char *description);
|
||||||
|
|
||||||
void free_string(char *ptr);
|
void free_string(char *ptr);
|
||||||
|
|
||||||
@ -145,8 +149,22 @@ FFIResult<MerchRecordVec> get_merchandise_list(const char *api_url,
|
|||||||
const char *api_key,
|
const char *api_key,
|
||||||
int32_t merchandise_list_id);
|
int32_t merchandise_list_id);
|
||||||
|
|
||||||
|
FFIResult<ShopRecord> get_shop(const char *api_url, const char *api_key, int32_t shop_id);
|
||||||
|
|
||||||
bool init();
|
bool init();
|
||||||
|
|
||||||
bool status_check(const char *api_url);
|
bool status_check(const char *api_url);
|
||||||
|
|
||||||
|
int32_t update_owner(const char *api_url,
|
||||||
|
const char *api_key,
|
||||||
|
uint32_t id,
|
||||||
|
const char *name,
|
||||||
|
uint32_t mod_version);
|
||||||
|
|
||||||
|
FFIResult<ShopRecord> update_shop(const char *api_url,
|
||||||
|
const char *api_key,
|
||||||
|
uint32_t id,
|
||||||
|
const char *name,
|
||||||
|
const char *description);
|
||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
@ -70,11 +70,9 @@ renaming_overrides_prefixing = false
|
|||||||
|
|
||||||
/* bad hack added by thallada. See: https://github.com/eqrion/cbindgen/issues/402 */
|
/* bad hack added by thallada. See: https://github.com/eqrion/cbindgen/issues/402 */
|
||||||
struct _Helper_0 {
|
struct _Helper_0 {
|
||||||
FFIResult<RefRecordVec> field;
|
FFIResult<RefRecordVec> ref_record_vec_result;
|
||||||
};
|
FFIResult<MerchRecordVec> merch_record_vec_result;
|
||||||
|
FFIResult<ShopRecord> shop_record_result;
|
||||||
struct _Helper_1 {
|
|
||||||
FFIResult<MerchRecordVec> field;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// dummy extern C block to close curly brace
|
// dummy extern C block to close curly brace
|
||||||
|
260
src/lib.rs
260
src/lib.rs
@ -79,6 +79,14 @@ impl Shop {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct ShopRecord {
|
||||||
|
id: i32,
|
||||||
|
name: *const c_char,
|
||||||
|
description: *const c_char,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
struct InteriorRef {
|
struct InteriorRef {
|
||||||
base_mod_name: String,
|
base_mod_name: String,
|
||||||
@ -238,11 +246,13 @@ unsafe impl Send for RefRecordVec {}
|
|||||||
unsafe impl Send for RefRecord {}
|
unsafe impl Send for RefRecord {}
|
||||||
unsafe impl Send for MerchRecordVec {}
|
unsafe impl Send for MerchRecordVec {}
|
||||||
unsafe impl Send for MerchRecord {}
|
unsafe impl Send for MerchRecord {}
|
||||||
|
unsafe impl Send for ShopRecord {}
|
||||||
unsafe impl<T> Sync for FFIResult<T> {}
|
unsafe impl<T> Sync for FFIResult<T> {}
|
||||||
unsafe impl Sync for RefRecordVec {}
|
unsafe impl Sync for RefRecordVec {}
|
||||||
unsafe impl Sync for RefRecord {}
|
unsafe impl Sync for RefRecord {}
|
||||||
unsafe impl Sync for MerchRecordVec {}
|
unsafe impl Sync for MerchRecordVec {}
|
||||||
unsafe impl Sync for MerchRecord {}
|
unsafe impl Sync for MerchRecord {}
|
||||||
|
unsafe impl Sync for ShopRecord {}
|
||||||
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -367,6 +377,71 @@ pub extern "C" fn create_owner(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Because C++ does not have Result, -1 means that the request was unsuccessful
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn update_owner(
|
||||||
|
api_url: *const c_char,
|
||||||
|
api_key: *const c_char,
|
||||||
|
id: u32,
|
||||||
|
name: *const c_char,
|
||||||
|
mod_version: u32,
|
||||||
|
) -> i32 {
|
||||||
|
info!("update_owner begin");
|
||||||
|
let api_url = unsafe { CStr::from_ptr(api_url) };
|
||||||
|
let api_key = unsafe { CStr::from_ptr(api_key) };
|
||||||
|
let name = unsafe { CStr::from_ptr(name) };
|
||||||
|
let api_url = api_url.to_string_lossy();
|
||||||
|
let api_key = api_key.to_string_lossy();
|
||||||
|
let name = name.to_string_lossy();
|
||||||
|
info!("api_url: {:?}", api_url);
|
||||||
|
info!("api_key: {:?}", api_key);
|
||||||
|
info!("name: {:?}", name);
|
||||||
|
info!("mod_version: {:?}", mod_version);
|
||||||
|
|
||||||
|
fn inner(api_url: &str, api_key: &str, id: u32, name: &str, mod_version: u32) -> Result<Owner> {
|
||||||
|
#[cfg(not(test))]
|
||||||
|
let url = Url::parse(api_url)?.join(&format!("v1/owners/{}", id))?;
|
||||||
|
#[cfg(test)]
|
||||||
|
let url = &mockito::server_url();
|
||||||
|
|
||||||
|
let owner = Owner::from_game(name, api_key, mod_version);
|
||||||
|
info!("created owner from game: {:?}", &owner);
|
||||||
|
if let Some(api_key) = &owner.api_key {
|
||||||
|
let client = reqwest::blocking::Client::new();
|
||||||
|
let resp = client
|
||||||
|
.patch(url)
|
||||||
|
.header("Api-Key", api_key.clone())
|
||||||
|
.json(&owner)
|
||||||
|
.send()?;
|
||||||
|
info!("update owner response from api: {:?}", &resp);
|
||||||
|
let bytes = resp.bytes()?;
|
||||||
|
let json: Owner = serde_json::from_slice(&bytes)?;
|
||||||
|
if let Some(id) = json.id {
|
||||||
|
let mut file = File::create(file_cache_dir(api_url)?.join(format!("owner_{}.json", id)))?;
|
||||||
|
file.write_all(&bytes.as_ref())?;
|
||||||
|
}
|
||||||
|
Ok(json)
|
||||||
|
} else {
|
||||||
|
Err(anyhow!("api-key not defined"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match inner(&api_url, &api_key, id, &name, mod_version) {
|
||||||
|
Ok(owner) => {
|
||||||
|
info!("update_owner successful");
|
||||||
|
if let Some(id) = owner.id {
|
||||||
|
id
|
||||||
|
} else {
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
error!("update_owner failed. {}", err);
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Because C++ does not have Result, -1 means that the request was unsuccessful
|
// Because C++ does not have Result, -1 means that the request was unsuccessful
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn create_shop(
|
pub extern "C" fn create_shop(
|
||||||
@ -374,7 +449,7 @@ pub extern "C" fn create_shop(
|
|||||||
api_key: *const c_char,
|
api_key: *const c_char,
|
||||||
name: *const c_char,
|
name: *const c_char,
|
||||||
description: *const c_char,
|
description: *const c_char,
|
||||||
) -> i32 {
|
) -> FFIResult<ShopRecord> {
|
||||||
info!("create_shop begin");
|
info!("create_shop begin");
|
||||||
let api_url = unsafe { CStr::from_ptr(api_url) };
|
let api_url = unsafe { CStr::from_ptr(api_url) };
|
||||||
let api_key = unsafe { CStr::from_ptr(api_key) };
|
let api_key = unsafe { CStr::from_ptr(api_key) };
|
||||||
@ -417,14 +492,191 @@ pub extern "C" fn create_shop(
|
|||||||
Ok(shop) => {
|
Ok(shop) => {
|
||||||
info!("create_shop successful");
|
info!("create_shop successful");
|
||||||
if let Some(id) = shop.id {
|
if let Some(id) = shop.id {
|
||||||
id
|
FFIResult::Ok(ShopRecord {
|
||||||
|
id,
|
||||||
|
name: CString::new(shop.name)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.into_raw(),
|
||||||
|
description: CString::new(shop.description)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.into_raw(),
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
-1
|
error!("create_shop failed. API did not return a shop with an ID");
|
||||||
|
let err_string = CString::new("API did not return a shop with an ID".to_string())
|
||||||
|
.expect("could not create CString")
|
||||||
|
.into_raw();
|
||||||
|
// TODO: also need to drop this CString once C++ is done reading it
|
||||||
|
FFIResult::Err(err_string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("create_shop failed. {}", err);
|
error!("create_shop failed. {}", err);
|
||||||
-1
|
// TODO: also need to drop this CString once C++ is done reading it
|
||||||
|
let err_string = CString::new(err.to_string())
|
||||||
|
.expect("could not create CString")
|
||||||
|
.into_raw();
|
||||||
|
FFIResult::Err(err_string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because C++ does not have Result, -1 means that the request was unsuccessful
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn update_shop(
|
||||||
|
api_url: *const c_char,
|
||||||
|
api_key: *const c_char,
|
||||||
|
id: u32,
|
||||||
|
name: *const c_char,
|
||||||
|
description: *const c_char,
|
||||||
|
) -> FFIResult<ShopRecord> {
|
||||||
|
info!("update_shop begin");
|
||||||
|
let api_url = unsafe { CStr::from_ptr(api_url) };
|
||||||
|
let api_key = unsafe { CStr::from_ptr(api_key) };
|
||||||
|
let name = unsafe { CStr::from_ptr(name) };
|
||||||
|
let description = unsafe { CStr::from_ptr(description) };
|
||||||
|
let api_url = api_url.to_string_lossy();
|
||||||
|
let api_key = api_key.to_string_lossy();
|
||||||
|
let name = name.to_string_lossy();
|
||||||
|
let description = description.to_string_lossy();
|
||||||
|
info!("api_url: {:?}", api_url);
|
||||||
|
info!("api_key: {:?}", api_key);
|
||||||
|
info!("name: {:?}", name);
|
||||||
|
info!("description: {:?}", description);
|
||||||
|
|
||||||
|
fn inner(api_url: &str, api_key: &str, id: u32, name: &str, description: &str) -> Result<Shop> {
|
||||||
|
#[cfg(not(test))]
|
||||||
|
let url = Url::parse(api_url)?.join(&format!("v1/shops/{}", id))?;
|
||||||
|
#[cfg(test)]
|
||||||
|
let url = &mockito::server_url();
|
||||||
|
|
||||||
|
let shop = Shop::from_game(name, description);
|
||||||
|
info!("created shop from game: {:?}", &shop);
|
||||||
|
let client = reqwest::blocking::Client::new();
|
||||||
|
let resp = client
|
||||||
|
.patch(url)
|
||||||
|
.header("Api-Key", api_key)
|
||||||
|
.json(&shop)
|
||||||
|
.send()?;
|
||||||
|
info!("update shop response from api: {:?}", &resp);
|
||||||
|
let bytes = resp.bytes()?;
|
||||||
|
let json: Shop = serde_json::from_slice(&bytes)?;
|
||||||
|
if let Some(id) = json.id {
|
||||||
|
let mut file = File::create(file_cache_dir(api_url)?.join(format!("shop_{}.json", id)))?;
|
||||||
|
file.write_all(&bytes.as_ref())?;
|
||||||
|
}
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
|
||||||
|
match inner(&api_url, &api_key, id, &name, &description) {
|
||||||
|
Ok(shop) => {
|
||||||
|
info!("update_shop successful");
|
||||||
|
if let Some(id) = shop.id {
|
||||||
|
FFIResult::Ok(ShopRecord {
|
||||||
|
id,
|
||||||
|
name: CString::new(shop.name)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.into_raw(),
|
||||||
|
description: CString::new(shop.description)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.into_raw(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
error!("create_shop failed. API did not return a shop with an ID");
|
||||||
|
let err_string = CString::new("API did not return a shop with an ID".to_string())
|
||||||
|
.expect("could not create CString")
|
||||||
|
.into_raw();
|
||||||
|
// TODO: also need to drop this CString once C++ is done reading it
|
||||||
|
FFIResult::Err(err_string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
error!("update_shop failed. {}", err);
|
||||||
|
// TODO: also need to drop this CString once C++ is done reading it
|
||||||
|
let err_string = CString::new(err.to_string())
|
||||||
|
.expect("could not create CString")
|
||||||
|
.into_raw();
|
||||||
|
FFIResult::Err(err_string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn get_shop(
|
||||||
|
api_url: *const c_char,
|
||||||
|
api_key: *const c_char,
|
||||||
|
shop_id: i32,
|
||||||
|
) -> FFIResult<ShopRecord> {
|
||||||
|
info!("get_shop begin");
|
||||||
|
let api_url = unsafe { CStr::from_ptr(api_url) };
|
||||||
|
let api_key = unsafe { CStr::from_ptr(api_key) };
|
||||||
|
let api_url = api_url.to_string_lossy();
|
||||||
|
let api_key = api_key.to_string_lossy();
|
||||||
|
info!("api_url: {:?}", api_url);
|
||||||
|
info!("api_key: {:?}", api_key);
|
||||||
|
|
||||||
|
fn inner(
|
||||||
|
api_url: &str,
|
||||||
|
api_key: &str,
|
||||||
|
shop_id: i32,
|
||||||
|
) -> Result<Shop> {
|
||||||
|
#[cfg(not(test))]
|
||||||
|
let url =
|
||||||
|
Url::parse(api_url)?.join(&format!("v1/shops/{}", shop_id))?;
|
||||||
|
#[cfg(test)]
|
||||||
|
let url = &mockito::server_url();
|
||||||
|
info!("api_url: {:?}", url);
|
||||||
|
|
||||||
|
let client = reqwest::blocking::Client::new();
|
||||||
|
let cache_path = file_cache_dir(api_url)?.join(format!("shop_{}.json", shop_id));
|
||||||
|
|
||||||
|
fn from_file_cache(cache_path: &Path) -> Result<Shop> {
|
||||||
|
let file = File::open(cache_path)?;
|
||||||
|
let reader = BufReader::new(file);
|
||||||
|
info!("get_shop returning value from cache: {:?}", cache_path);
|
||||||
|
Ok(serde_json::from_reader(reader)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
match client.get(url).header("Api-Key", api_key).send() {
|
||||||
|
Ok(resp) => {
|
||||||
|
info!("get_shop response from api: {:?}", &resp);
|
||||||
|
if !resp.status().is_server_error() {
|
||||||
|
let mut file = File::create(&cache_path)?;
|
||||||
|
let bytes = resp.bytes()?;
|
||||||
|
file.write_all(&bytes.as_ref())?;
|
||||||
|
let json = serde_json::from_slice(&bytes)?;
|
||||||
|
Ok(json)
|
||||||
|
} else {
|
||||||
|
from_file_cache(&cache_path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
error!("get_shop api request error: {}", err);
|
||||||
|
from_file_cache(&cache_path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match inner(&api_url, &api_key, shop_id) {
|
||||||
|
Ok(shop) => {
|
||||||
|
// TODO: need to pass this back into Rust once C++ is done with it so it can be manually dropped and the CStrings dropped from raw pointers.
|
||||||
|
FFIResult::Ok(ShopRecord {
|
||||||
|
id: shop_id,
|
||||||
|
name: CString::new(shop.name)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.into_raw(),
|
||||||
|
description: CString::new(shop.description)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.into_raw(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
error!("get_shop_list failed. {}", err);
|
||||||
|
let err_string = CString::new(err.to_string())
|
||||||
|
.expect("could not create CString")
|
||||||
|
.into_raw();
|
||||||
|
// TODO: also need to drop this CString once C++ is done reading it
|
||||||
|
FFIResult::Err(err_string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user