| 1 | use std::ffi::{CStr, CString}; | 
| 2 | use std::fmt; | 
|---|
| 3 | use std::ptr; | 
|---|
| 4 |  | 
|---|
| 5 | use crate::Error; | 
|---|
| 6 |  | 
|---|
| 7 | /// A linked list of a strings | 
|---|
| 8 | pub struct List { | 
|---|
| 9 | raw: *mut curl_sys::curl_slist, | 
|---|
| 10 | } | 
|---|
| 11 |  | 
|---|
| 12 | /// An iterator over `List` | 
|---|
| 13 | #[ derive(Clone)] | 
|---|
| 14 | pub struct Iter<'a> { | 
|---|
| 15 | _me: &'a List, | 
|---|
| 16 | cur: *mut curl_sys::curl_slist, | 
|---|
| 17 | } | 
|---|
| 18 |  | 
|---|
| 19 | pub fn raw(list: &List) -> *mut curl_sys::curl_slist { | 
|---|
| 20 | list.raw | 
|---|
| 21 | } | 
|---|
| 22 |  | 
|---|
| 23 | pub unsafe fn from_raw(raw: *mut curl_sys::curl_slist) -> List { | 
|---|
| 24 | List { raw } | 
|---|
| 25 | } | 
|---|
| 26 |  | 
|---|
| 27 | unsafe impl Send for List {} | 
|---|
| 28 |  | 
|---|
| 29 | impl List { | 
|---|
| 30 | /// Creates a new empty list of strings. | 
|---|
| 31 | pub fn new() -> List { | 
|---|
| 32 | List { | 
|---|
| 33 | raw: ptr::null_mut(), | 
|---|
| 34 | } | 
|---|
| 35 | } | 
|---|
| 36 |  | 
|---|
| 37 | /// Appends some data into this list. | 
|---|
| 38 | pub fn append(&mut self, data: &str) -> Result<(), Error> { | 
|---|
| 39 | let data = CString::new(data)?; | 
|---|
| 40 | unsafe { | 
|---|
| 41 | let raw = curl_sys::curl_slist_append(self.raw, data.as_ptr()); | 
|---|
| 42 | assert!(!raw.is_null()); | 
|---|
| 43 | self.raw = raw; | 
|---|
| 44 | Ok(()) | 
|---|
| 45 | } | 
|---|
| 46 | } | 
|---|
| 47 |  | 
|---|
| 48 | /// Returns an iterator over the nodes in this list. | 
|---|
| 49 | pub fn iter(&self) -> Iter { | 
|---|
| 50 | Iter { | 
|---|
| 51 | _me: self, | 
|---|
| 52 | cur: self.raw, | 
|---|
| 53 | } | 
|---|
| 54 | } | 
|---|
| 55 | } | 
|---|
| 56 |  | 
|---|
| 57 | impl fmt::Debug for List { | 
|---|
| 58 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 
|---|
| 59 | f&mut DebugList<'_, '_>.debug_list() | 
|---|
| 60 | .entries(self.iter().map(String::from_utf8_lossy)) | 
|---|
| 61 | .finish() | 
|---|
| 62 | } | 
|---|
| 63 | } | 
|---|
| 64 |  | 
|---|
| 65 | impl<'a> IntoIterator for &'a List { | 
|---|
| 66 | type IntoIter = Iter<'a>; | 
|---|
| 67 | type Item = &'a [u8]; | 
|---|
| 68 |  | 
|---|
| 69 | fn into_iter(self) -> Iter<'a> { | 
|---|
| 70 | self.iter() | 
|---|
| 71 | } | 
|---|
| 72 | } | 
|---|
| 73 |  | 
|---|
| 74 | impl Drop for List { | 
|---|
| 75 | fn drop(&mut self) { | 
|---|
| 76 | unsafe { curl_sys::curl_slist_free_all(self.raw) } | 
|---|
| 77 | } | 
|---|
| 78 | } | 
|---|
| 79 |  | 
|---|
| 80 | impl<'a> Iterator for Iter<'a> { | 
|---|
| 81 | type Item = &'a [u8]; | 
|---|
| 82 |  | 
|---|
| 83 | fn next(&mut self) -> Option<&'a [u8]> { | 
|---|
| 84 | if self.cur.is_null() { | 
|---|
| 85 | return None; | 
|---|
| 86 | } | 
|---|
| 87 |  | 
|---|
| 88 | unsafe { | 
|---|
| 89 | let ret: Option<&[u8]> = Some(CStr::from_ptr((*self.cur).data).to_bytes()); | 
|---|
| 90 | self.cur = (*self.cur).next; | 
|---|
| 91 | ret | 
|---|
| 92 | } | 
|---|
| 93 | } | 
|---|
| 94 | } | 
|---|
| 95 |  | 
|---|
| 96 | impl<'a> fmt::Debug for Iter<'a> { | 
|---|
| 97 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 
|---|
| 98 | f&mut DebugList<'_, '_>.debug_list() | 
|---|
| 99 | .entries(self.clone().map(String::from_utf8_lossy)) | 
|---|
| 100 | .finish() | 
|---|
| 101 | } | 
|---|
| 102 | } | 
|---|
| 103 |  | 
|---|