mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-07-24 19:22:51 +02:00
113 lines
3.3 KiB
Rust
113 lines
3.3 KiB
Rust
use crate::*;
|
|
use crate::bindings::capi as ztcore;
|
|
use std::os::raw::{c_char, c_int, c_uint};
|
|
use std::ffi::CString;
|
|
|
|
pub struct Locator {
|
|
pub(crate) capi: *const ztcore::ZT_Locator,
|
|
requires_delete: bool
|
|
}
|
|
|
|
impl Locator {
|
|
#[inline]
|
|
pub(crate) fn new_from_capi(l: *const ztcore::ZT_Locator, requires_delete: bool) -> Locator {
|
|
Locator{
|
|
capi: l,
|
|
requires_delete: requires_delete
|
|
}
|
|
}
|
|
|
|
pub fn new_from_string(s: &str) -> Result<Locator, ResultCode> {
|
|
unsafe {
|
|
let cs = CString::new(s);
|
|
if cs.is_err() {
|
|
return Err(ResultCode::ErrorBadParameter);
|
|
}
|
|
let cs = cs.unwrap();
|
|
let l = ztcore::ZT_Locator_fromString(cs.as_ptr());
|
|
if l.is_null() {
|
|
return Err(ResultCode::ErrorBadParameter);
|
|
}
|
|
return Ok(Locator::new_from_capi(l, true));
|
|
}
|
|
}
|
|
|
|
pub fn timestamp(&self) -> i64 {
|
|
unsafe {
|
|
return ztcore::ZT_Locator_timestamp(self.capi) as i64;
|
|
}
|
|
}
|
|
|
|
pub fn endpoints(&self) -> Box<[Endpoint]> {
|
|
let mut eps: Vec<Endpoint> = Vec::new();
|
|
unsafe {
|
|
let ep_count = ztcore::ZT_Locator_endpointCount(self.capi) as usize;
|
|
eps.reserve(ep_count as usize);
|
|
for i in 0..ep_count {
|
|
let ep = ztcore::ZT_Locator_endpoint(self.capi, i as c_uint);
|
|
if !ep.is_null() {
|
|
eps.push(Endpoint::new_from_capi(&(*ep)));
|
|
}
|
|
}
|
|
}
|
|
eps.into_boxed_slice()
|
|
}
|
|
}
|
|
|
|
impl Drop for Locator {
|
|
fn drop(&mut self) {
|
|
if self.requires_delete {
|
|
unsafe {
|
|
ztcore::ZT_Locator_delete(self.capi);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Clone for Locator {
|
|
fn clone(&self) -> Locator {
|
|
Locator::new_from_string(self.to_string().as_str()).ok().unwrap()
|
|
}
|
|
}
|
|
|
|
impl ToString for Locator {
|
|
fn to_string(&self) -> String {
|
|
let mut buf: [u8; 4096] = [0; 4096];
|
|
unsafe {
|
|
if ztcore::ZT_Locator_toString(self.capi, buf.as_mut_ptr() as *mut c_char, buf.len() as c_int).is_null() {
|
|
return String::from("(invalid)");
|
|
}
|
|
return cstr_to_string(buf.as_ptr() as *const c_char, 4096);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl serde::Serialize for Locator {
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer {
|
|
serializer.serialize_str(self.to_string().as_str())
|
|
}
|
|
}
|
|
|
|
struct LocatorVisitor;
|
|
|
|
impl<'de> serde::de::Visitor<'de> for LocatorVisitor {
|
|
type Value = Locator;
|
|
|
|
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
formatter.write_str("Locator value in string form")
|
|
}
|
|
|
|
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> where E: serde::de::Error {
|
|
let id = Locator::new_from_string(s);
|
|
if id.is_err() {
|
|
return Err(serde::de::Error::invalid_value(serde::de::Unexpected::Str(s), &self));
|
|
}
|
|
return Ok(id.ok().unwrap() as Self::Value);
|
|
}
|
|
}
|
|
|
|
impl<'de> serde::Deserialize<'de> for Locator {
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de> {
|
|
deserializer.deserialize_str(LocatorVisitor)
|
|
}
|
|
}
|