use std::ffi::CStr;
use crate::ffi::libscamperctrl::{self, ScamperVpT};
pub struct ScamperVp {
pub(crate) inner: *mut ScamperVpT,
}
impl ScamperVp {
pub(crate) unsafe fn from_ptr(ptr: *mut ScamperVpT) -> Option<Self> {
if ptr.is_null() { return None; }
let ptr = unsafe { libscamperctrl::scamper_vp_use(ptr) };
Some(ScamperVp { inner: ptr })
}
pub fn name(&self) -> Option<String> {
let ptr = unsafe { libscamperctrl::scamper_vp_name_get(self.inner) };
if ptr.is_null() { None } else {
Some(unsafe { CStr::from_ptr(ptr) }.to_string_lossy().into_owned())
}
}
pub fn shortname(&self) -> Option<String> {
let ptr = unsafe { libscamperctrl::scamper_vp_shortname_get(self.inner) };
if !ptr.is_null() {
return Some(unsafe { CStr::from_ptr(ptr) }.to_string_lossy().into_owned());
}
self.name()
}
pub fn ipv4(&self) -> Option<String> {
let ptr = unsafe { libscamperctrl::scamper_vp_ipv4_get(self.inner) };
if ptr.is_null() { None } else {
Some(unsafe { CStr::from_ptr(ptr) }.to_string_lossy().into_owned())
}
}
pub fn asn4(&self) -> Option<String> {
let ptr = unsafe { libscamperctrl::scamper_vp_asn4_get(self.inner) };
if ptr.is_null() { None } else {
Some(unsafe { CStr::from_ptr(ptr) }.to_string_lossy().into_owned())
}
}
pub fn cc(&self) -> Option<String> {
let ptr = unsafe { libscamperctrl::scamper_vp_cc_get(self.inner) };
if ptr.is_null() { None } else {
Some(unsafe { CStr::from_ptr(ptr) }.to_string_lossy().to_uppercase())
}
}
pub fn st(&self) -> Option<String> {
let ptr = unsafe { libscamperctrl::scamper_vp_st_get(self.inner) };
if ptr.is_null() { None } else {
Some(unsafe { CStr::from_ptr(ptr) }.to_string_lossy().to_uppercase())
}
}
pub fn place(&self) -> Option<String> {
let ptr = unsafe { libscamperctrl::scamper_vp_place_get(self.inner) };
if ptr.is_null() { None } else {
Some(unsafe { CStr::from_ptr(ptr) }.to_string_lossy().into_owned())
}
}
pub fn iata(&self) -> Option<String> {
let ptr = unsafe { libscamperctrl::scamper_vp_iata_get(self.inner) };
if ptr.is_null() { None } else {
Some(unsafe { CStr::from_ptr(ptr) }.to_string_lossy().to_uppercase())
}
}
pub fn loc(&self) -> Option<(f64, f64)> {
let ptr = unsafe { libscamperctrl::scamper_vp_latlong_get(self.inner) };
if ptr.is_null() { return None; }
let s = unsafe { CStr::from_ptr(ptr) }.to_str().ok()?;
let mut parts = s.splitn(2, ',');
let lat = parts.next()?.parse().ok()?;
let lon = parts.next()?.parse().ok()?;
Some((lat, lon))
}
pub fn tags(&self) -> Vec<String> {
let count = unsafe { libscamperctrl::scamper_vp_tagc_get(self.inner) };
let mut tags = Vec::with_capacity(count);
for i in 0..count {
let ptr = unsafe { libscamperctrl::scamper_vp_tag_get(self.inner, i) };
if !ptr.is_null() {
tags.push(unsafe { CStr::from_ptr(ptr) }.to_string_lossy().into_owned());
}
}
tags
}
}
impl Drop for ScamperVp {
fn drop(&mut self) {
unsafe { libscamperctrl::scamper_vp_free(self.inner) };
}
}
impl Clone for ScamperVp {
fn clone(&self) -> Self {
let ptr = unsafe { libscamperctrl::scamper_vp_use(self.inner) };
ScamperVp { inner: ptr }
}
}
impl PartialEq for ScamperVp {
fn eq(&self, other: &Self) -> bool { self.inner == other.inner }
}
impl Eq for ScamperVp {}
impl std::hash::Hash for ScamperVp {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
(self.inner as usize).hash(state);
}
}
impl std::fmt::Display for ScamperVp {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.name() {
Some(n) => write!(f, "{}", n),
None => write!(f, "<ScamperVp {:p}>", self.inner),
}
}
}
unsafe impl Send for ScamperVp {}
unsafe impl Sync for ScamperVp {}