1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
use ffi::{TXTRecordRef, TXTRecordCreate, TXTRecordDeallocate, TXTRecordSetValue, TXTRecordRemoveValue, TXTRecordGetLength, TXTRecordGetBytesPtr, TXTRecordContainsKey, TXTRecordGetValuePtr, TXTRecordGetCount, TXTRecordGetItemAtIndex, DNSServiceErrorType}; use std::mem::uninitialized; use libc::{uint8_t, c_void, c_char, malloc, free}; use std::cmp::min; use std::ops::Drop; use std::ptr::{null, null_mut}; use utils::{str_to_const_c, mut_c_to_string}; pub struct TXTRecord { pub ptr : TXTRecordRef, pub buffer : Option<Vec<u8>>, } pub struct TXTRecordData { pub ptr : *const c_void, pub len : u16, } pub struct TXTRecordItem <'a, T: 'a> { pub key : String, pub value_len : u8, pub value : &'a T, } impl TXTRecord { pub fn new () -> TXTRecord { let mut ret = TXTRecord { ptr : unsafe { uninitialized () }, buffer : None, }; unsafe { TXTRecordCreate (&mut ret.ptr, 0, null_mut ()) }; ret } pub fn new_with_buffer (size : u16) -> TXTRecord { let mut ret = TXTRecord { ptr : unsafe { uninitialized () }, buffer : Some (vec![0; size as usize]), }; unsafe { TXTRecordCreate (&mut ret.ptr, size, &mut ret.buffer as *mut _ as *mut c_void) }; ret } pub fn set_value <T> (&mut self, key : &str, value_wrapper : Option<T>) -> DNSServiceErrorType where T : Into<Vec<u8>> { unsafe { let new_key = str_to_const_c (key); match value_wrapper { None => TXTRecordSetValue (&mut self.ptr, new_key, 0, null ()), Some (value) => { let value_array = value.into (); TXTRecordSetValue (&mut self.ptr, new_key, value_array.len () as u8, value_array.as_ptr () as *const c_void) }, } } } pub fn remove_value (&mut self, key : &str) -> DNSServiceErrorType { unsafe { TXTRecordRemoveValue (&mut self.ptr, str_to_const_c (key)) } } pub fn get_length (&self) -> u16 { unsafe { TXTRecordGetLength (&self.ptr) } } pub fn get_bytes_ptr (&self) -> *const c_void { unsafe { TXTRecordGetBytesPtr (&self.ptr) } } pub fn get_data (&self) -> TXTRecordData { TXTRecordData { ptr : self.get_bytes_ptr (), len : self.get_length (), } } } impl TXTRecordData { pub fn contains_key (&self, key : &str) -> bool { let result = unsafe { TXTRecordContainsKey (self.len, self.ptr, str_to_const_c (key)) }; match result { 1 => true, _ => false, } } pub fn get_value_ptr <'a, T> (&'a self, key : &'a str) -> Option<TXTRecordItem<T>> { unsafe { let value_len : *mut uint8_t = uninitialized (); let value = TXTRecordGetValuePtr (self.len, self.ptr, str_to_const_c (key), value_len); if value == null () { None } else { let value = & *(value as *const T); Some(TXTRecordItem { key : String::from (key), value_len : *value_len, value : value, }) } } } pub fn get_count (&self) -> u16 { unsafe { TXTRecordGetCount (self.len, self.ptr) } } pub fn get_item_at_index <T> (&self, index : u16, key_buffer_len : Option<usize>) -> Result<TXTRecordItem<T>, DNSServiceErrorType> { unsafe { let keybuffer = match key_buffer_len { None => malloc (256), Some (value) => { let limit = min (value, 256); malloc (limit as u64) } } as *mut c_char; let value_len : *mut uint8_t = uninitialized (); let value_ptr = uninitialized (); match TXTRecordGetItemAtIndex (self.len, self.ptr, index, 256, keybuffer, value_len, value_ptr) { DNSServiceErrorType::NoError => { let value = & *(*(value_ptr) as *const T); let keyvalue = mut_c_to_string (keybuffer); free (keybuffer as *mut c_void); Ok(TXTRecordItem { key : keyvalue, value_len : *value_len, value : value, }) }, result @ _ => Err(result), } } } } impl Drop for TXTRecord { fn drop (&mut self) { unsafe { TXTRecordDeallocate (&mut self.ptr) }; } }